home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The 640 MEG Shareware Studio 1
/
The 640 Meg Shareware Studio CD-ROM Volume I (Data Express)(1992).ISO
/
driver
/
macpab1.dsk
/
MACPA1.ZIP
/
AUDIODD
/
SOURCE
/
DEMO.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-06-30
|
210KB
|
4,900 lines
/**************************************************************************/
/* (C)Copyright International Business Machines Corp. 1991, 1992. */
/* */
/* All Rights Reserved. */
/* */
/* Refer to "LICENSE.DOC" for information regarding the use of this file. */
/* */
/**************************************************************************/
/* */
/* Title: ACPA Demo */
/* */
/* Created by: Bridget Ritthaler */
/* */
/* Description: This is a demo program for the ACPA card. This program */
/* supports recording MIDI data to a standard MIDI file */
/* and waveform data to a RIFF - WAVE file. It also supports */
/* playing standard MIDI files and both waveform and MIDI */
/* data RIFF files. */
/* */
/* Operating Systems: Both DOS and OS/2 are supported. They each require */
/* seperate builds. */
/* */
/**************************************************************************/
/*****************************************************************************/
/* SYSTEM INCLUDES */
/*****************************************************************************/
#if IS_OS2
#define INCL_DOSSEMAPHORES
#define INCL_DOSPROCESS
#endif
#include "demodef.h" /* #define header file */
#include "demomsg.h" /* All displayed messages */
#if IS_OS2
#include <os2.h> /* Use MS C 6.00A */
#else
#include <dos.h> /* IBM C/2 or MS C */
#endif
#include "audiodd.h" /* Audio Device Driver structures */
#include <graph.h> /* Display routines in IBM C/2 */
/* (Must use MS C 6.00A for OS/2) */
#include <conio.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h> /* File I/O flags */
#include <sys\types.h> /* File status/time types */
#include <sys\stat.h> /* File status flags/structs */
#include <io.h> /* File IO declarations */
#include <errno.h> /* File I/O error constants */
#include <malloc.h> /* _fmalloc() and _ffree() */
unsigned long num_of_f8s = 0;
/*****************************************************************************/
/* RESIDENT FUNCTION DECLARATIONS */
/*****************************************************************************/
unsigned char nextbyte (int trk);
void freebuffs(unsigned int, unsigned int);
int read_kb (char*,unsigned int);
void outmsg (int type, int msg_num);
void outemsg (int type, int msg_num);
void endemsg (int type);
void restore (short, long, struct rccoord);
int midi2seq (unsigned long);
int seq2midi (unsigned char*, int, unsigned long *);
int audrec (void);
int audplay (void);
int write_midi_headers(void);
int write_riff_headers(void);
int write_midi_lengths(void);
int write_riff_lengths(void);
int send_data(unsigned char *, unsigned long, int);
void update_count(void);
void buff_data(unsigned char);
int play_data(unsigned long, struct audio_init);
void dcwrite(char *data, int len, unsigned int num_buffers);
void change_settings(void);
int (far *direct_call)(int,char far *,int);
#if IS_DOS
int ioctl(void far *Data,unsigned char Function,int DevHandle);
int dspload(char *name, int audstr);
extern void callback(void);
#else
int dspload(char *name, HFILE audstr);
#endif
/*****************************************************************************/
/* VARIABLE DECLARATION/DEFINITIONS */
/*****************************************************************************/
int chan_i;
int file_type;
int monitor=1;
int cb_flag; /* flag for callback function to be included */
int pos_flag; /* flag for display of position value to be included */
int update_flag; /* flag for AUDIO_UPDATE processing */
unsigned int update_index; /* index into update_array */
char sem_name[] = {"\\sem\\demowait1.sem"};
unsigned long delay;
char wasur;
unsigned int batch_time;
struct update_array_s {
unsigned long length; /* note - user may pass in >1 buff */
char far *Virt; /* User's virtual address */
} update_array[16];
struct track_info devinfo;
#if IS_DOS
union REGS dosregs;
#else
unsigned short ActionTaken;
#endif
struct devid dev_input;
struct devid dev_output;
char batch = FALSE;
int index;
unsigned long argint;
char *stopstring;
char iname[MAXSTRING]; /* MIDI file to be played */
char filerate[MAXSTRING]; /* Type of file being played */
char old_string_read[MAXSTRING]; /* last MIDI file played */
char delta_time; /* flag to see if delta_time was just */
/* written or if 0 time should be added*/
char status[9] = {"Stopped "};
char cur_balance_s[7] = {"Middle"};
char cur_volume_s[11] = {"---------*"};
char audioname[9] = "AUDIO1$";
unsigned char midi_buff[MIDI_BUFF_LEN];
unsigned int midi_buff_index;
unsigned char RIFF_header[8] = {'R','I','F','F','0','0','0','0'};
unsigned char WAVE_header[4] = {'W','A','V','E'};
unsigned char ibmw_header[4] = {'i','b','m','w'};
unsigned char fmt_header[8] = {'f','m','t',' ','0','0','0','0'};
unsigned char data_header[8] = {'d','a','t','a','0','0','0','0'};
unsigned char tempo_meda[7] = {0, 0xff, 0x51, 3, 0, 0, 0};
unsigned char header[14] = {'M','T','h','d',0,0,0,6,0,0,0,1,0,0x78};
/* chunk_type[4] 0-3 MThd ASCII characters */
/* length 4-7 length of header data */
/* format 8-9 overall organization of the file */
/* note: only format = 0 supported */
/* ntrks 10-11 number of track chunks in the file */
/* note: always 1 for format 0 */
/* division 12-13 meaning of the delta-times */
/* note: SMPTE time not supported */
unsigned char eot_meda[4] = {0, 0xff, 0x2F, 0};
unsigned char track[8] = {'M','T','r','k',0,0,0,0};
/* chunk_type[4] 0-3 MTrk ASCII characters */
/* length 4-7 length of header data */
unsigned char timinit[10] = { 0xf0, 0, 0, 0x3a, 3, 1, 0x08, 3, 0, 0xf7 };
unsigned char timesysex[8] = { 0xf0, 0, 0, 0x3a, 1, 0, 0, 0xf7 };
unsigned char tempo_sysex[10] = { 0xf0,0,0,0x3a,3,2,0,0,0,0xf7 };
int inhndl, /* File handle for input file */
last_data_bytes, /* total number of bytes for the */
/* running status */
data_bytes; /* number of data bytes that go with */
/* current status */
#if IS_DOS
int audhndl; /* Low level I/O file handle for */
int saudhndl;
#else /* AUDIO1 device */
HFILE audhndl;
HFILE saudhndl;
#endif
int started; /* current play/record status */
int rc; /* return code from function calls */
int x,y; /* loop counter for MODE determination*/
unsigned int sy;
int user_esc; /* flag to determine when to exit */
int eat; /* number of data bytes to eat */
long runtotal; /* total # bytes played/recorded by DD*/
long old_runtotal;
long playtotal=0; /* total # bytes played by the DD */
long old_playtotal=0;
long cur_volume = 0x7fffffff;
long cur_balance = 0x3fffffff;
long cur_input = STEREO_LINE_INPUT;
unsigned char timinitr[10] = { 0xf0, 0, 0, 0x3a, 3, 1, 0x18, 3, 0, 0xf7 };
unsigned char *trkdata[128]; /* Up to 128 tracks */
unsigned char running_status; /* last status byte */
unsigned int remtracks; /* # remaining tracks to do */
unsigned long delta[128]; /* # clocks to next event */
unsigned long trklen[128]; /* Track remaining lengths */
long esc_count; /* Count left in buffer when ESC hit */
/* during a record */
#if IS_OS2
HSEM callback;
unsigned long error_count=0;
#endif
unsigned long interrupt_count=0;
struct audio_init init; /* structure for audio initialization */
int exit_ch=FALSE;
int channels; /* 1 = mono 2 = stereo */
/* mode_table structure */
struct mode_data {
short mode; /* mode # */
long flags_mask; /* relevant flags */
long flags; /* flag values */
short bps_low; /* bits_per_sample lower limit */
short bps_high; /* bits_per_sample upper limit */
long srate_low; /* srate lower limit */
long srate_high; /* srate upper limit */
short channels_low; /* channels lower limit */
short channels_high; /* channels upper limit */
long bsize; /* block size */
short dont_care; /* bitmap of don't-care values */
};
struct mode_data mode_table[NUM_MODES] = {
MIDI,0,0,8,8,0,0,0,0,1,FLAGS+BPS+SRATE+CHANNELS+BSIZE, //MIDI
ADPCM,FIXED,FIXED,16,16,11025,11025,1,1,576,BPS+BSIZE, //AVC VOICE
ADPCM,FIXED,FIXED,16,16,22050,22050,1,1,1128,BPS+BSIZE,//AVC MUSIC
ADPCM,FIXED,FIXED,16,16,22050,22050,2,2,2256,BPS+BSIZE,//AVC STEREO
ADPCM,FIXED,FIXED,16,16,44100,44100,1,1,1128,BPS+BSIZE,//AVC HIGH QUALITY
PCM,0x3e,0,8,8,8000,8000,1,2,0,BSIZE, //PCM 8 bit 8K
PCM,0x3e,0,8,8,11025,11025,1,2,0,BSIZE, //PCM 8 bit 11K
PCM,0x3e,0,8,8,22050,22050,1,2,0,BSIZE, //PCM 8 bit 22K
PCM,0x3e,0,8,8,44100,44100,1,2,0,BSIZE, //PCM 8 bit 44K
PCM,0x3e,TWOS_COMPLEMENT,16,16,8000,8000,1,2,0,BSIZE, //PCM 16 bit 8K
PCM,0x3e,TWOS_COMPLEMENT,16,16,11025,11025,1,2,0,BSIZE,//PCM 16 bit 11K
PCM,0x3e,TWOS_COMPLEMENT,16,16,22050,22050,1,2,0,BSIZE,//PCM 16 bit 22K
PCM,0x3e,TWOS_COMPLEMENT,16,16,44100,44100,1,2,0,BSIZE,//PCM 16 bit 44K
PCM,0x3e,0,8,8,0,44100,1,1,0,BSIZE+SRATE, //Other 8 bit PCM
PCM,0x3e,0,16,16,0,44100,1,1,0,BSIZE+SRATE, //Other 16 bit PCM
SOURCE_MIX,0,0,8,8,8000,8000,1,1,0,FLAGS+BPS+BSIZE+SRATE+CHANNELS,//Source Mix
MU_LAW,0x3e,0,8,8,8000,8000,1,2,0,BSIZE, //Mu-Law 8 bit 8K
MU_LAW,0x3e,0,8,8,11025,11025,1,2,0,BSIZE, //Mu-Law 8 bit 11K
MU_LAW,0x3e,0,8,8,22050,22050,1,2,0,BSIZE, //Mu-Law 8 bit 22K
MU_LAW,0x3e,0,8,8,44100,44100,1,2,0,BSIZE, //Mu-Law 8 bit 44K
A_LAW,0x3e,0,8,8,8000,8000,1,2,0,BSIZE, //A-Law 8 bit 8K
A_LAW,0x3e,0,8,8,11025,11025,1,2,0,BSIZE, //A-Law 8 bit 11K
A_LAW,0x3e,0,8,8,22050,22050,1,2,0,BSIZE, //A-Law 8 bit 22K
A_LAW,0x3e,0,8,8,44100,44100,1,2,0,BSIZE, //A-Law 8 bit 44K
CLAIM_HDWR,0,0,0,0,0,0,0,0,0,FLAGS+BPS+BSIZE+SRATE+CHANNELS,//Claim Hardware
CVSD,0x3e,0,0,0,0,0,1,1,0,BSIZE, // CVSD - 0
CVSD,0x3e,0,0,1,1,0,1,1,0,BSIZE, // CVSD - 1
CVSD,0x3e,0,0,2,2,0,1,1,0,BSIZE, // CVSD - 2
CVSD,0x3e,0,0,3,3,0,1,1,0,BSIZE, // CVSD - 3
CVSD,0x3e,0,0,4,4,0,1,1,0,BSIZE, // CVSD - 4
CVSD,0x3e,0,0,5,5,0,1,1,0,BSIZE, // CVSD - 5
PCM,0x3e,0,8,8,7875,7875,1,2,0,BSIZE+FLAGS, /* 7875K 8b PCM */
PCM,0x3e,0,8,8,31500,31500,1,2,0,BSIZE+FLAGS, /* 31500k 8b PCM */
PCM,0x3e,0,8,8,48000,48000,1,2,0,BSIZE+FLAGS, /* 48000k 8b PCM */
PCM,0x3e,0,16,16,7875,7875,1,2,0,BSIZE+FLAGS, /* 7875K 8b PCM */
PCM,0x3e,0,16,16,31500,31500,1,2,0,BSIZE+FLAGS, /* 31500k 8b PCM */
PCM,0x3e,0,16,16,48000,48000,1,2,0,BSIZE+FLAGS, /* 48000k 8b PCM */
MU_LAW,0x3e,0,8,8,7875,7875,1,2,0,BSIZE+FLAGS, /* 7875k 8b Mu-Law*/
MU_LAW,0x3e,0,8,8,31500,31500,1,1,0,BSIZE+FLAGS, /* 31500k 8b Mu-Law*/
MU_LAW,0x3e,0,8,8,48000,48000,1,1,0,BSIZE+FLAGS, /* 48000k 8b Mu-Law*/
A_LAW,0x3e,0,8,8,7875,7875,1,2,0,BSIZE+FLAGS, /* 7875k 8b A-Law */
A_LAW,0x3e,0,8,8,31500,31500,1,1,0,BSIZE+FLAGS, /* 31500k 8b A-Law*/
A_LAW,0x3e,0,8,8,48000,48000,1,1,0,BSIZE+FLAGS /* 48000k 8b A-Law*/
};
int mode = 0; /* MIDI by default */
int mode_i = 0; /* Index into mode_table */
char mode_s[10]; /* String to input mode from screen */
char rate_s[8]; /* String to type of mode from screen*/
unsigned long blocksize=280;
unsigned int num_rbuffers_r = 1;
struct iobuf far *rbuf; /* transmit buffer */
char far *rbuffer;
unsigned int rbuffer_len_p[1] = {RBUFFERSIZEP};
unsigned int rbuffer_len_r[128] = {RBUFFERSIZER};
unsigned long rlength = RBUFFERSIZER;
unsigned int num_xbuffers_p = 1;
struct iobuf far *xbuf; /* transmit buffer */
char far *xbuffer;
unsigned int xbuffer_len_p[128] = {XBUFFERSIZEP};
unsigned int xbuffer_len_r[1] = {XBUFFERSIZER};
unsigned long xlength = XBUFFERSIZEP;
unsigned int update_segnum;
unsigned int prv_segnum;
unsigned int available_buffs;
unsigned int rtn_segnum;
unsigned long update_cnt;
unsigned long update_size;
unsigned char far *update_ptr;
unsigned int old_segnum;
unsigned int new_segnum;
char far *old_tail;
char far *new_tail;
char supress=0;
char mastervol=0;
char audiowait=0;
int source_input = DEFAULT_INPUT;
int source_output = DEFAULT_OUTPUT;
char source_input_s[2];
char source_output_s[2];
int function; /* 0 if playback demo */
#if IS_OS2
short priority;
PIDINFO PidInfo;
#endif
int x;
void main(argc,argv)
int argc;
char *argv[];
{
/*****************************************************************************/
/* LOCAL VARIABLE DEFINITIONS */
/*****************************************************************************/
short oldfgd; /* original foreground color */
int okfile; /* flag for valid filename */
/* 1 if record demo */
int x,ch; /* character holder */
int not_picked; /* flag for while loop */
int not_picked_s; /* flag for while loop */
int inputmsgnum;
long oldbgd; /* original background color */
struct rccoord oldpos; /* original cursor position */
/**************************************************************************/
/* Start of Code */
/**************************************************************************/
/* Save original foreground, background, and text positions */
oldfgd = _gettextcolor();
oldbgd = _getbkcolor();
oldpos = _gettextposition();
/* Set background color and clear the screen */
_setbkcolor(BLUE);
_clearscreen(_GCLEARSCREEN);
outmsg(TITLE,GENERAL); /* Write out general welcome title */
outmsg(COPYRIGHT,0); /* Write Copyright msg to display */
cb_flag = 0; /* initialize for no callback */
delay = 0; /* initialize for no delay */
update_flag = 0; /* initialize for no AUDIO_UPDATE */
/* Parse input parameters */
for(x=1; x<argc; x++){
strupr(argv[x]);
if(*argv[x]=='?'){
outmsg(CLHELP,HELPHELP);
return;
}else if(!strcmp(argv[x],"/B?")){
outmsg(CLHELP,BATCHHELP);
return;
} else if(!strcmp(argv[x],"/C")) {
// if ((++x >= argc) || (!(cb_flag = atoi(argv[x]) & 0x0F00))){
if ((++x >= argc) ||
(*argv[x]<'1') || (*argv[x]>'9')) { /* callback number */
outemsg(ERROR,CBINVALID);
cb_flag = 0;
} else {
sem_name[14] = *argv[x]; /* Copy number to our sem name */
if ((++x >= argc) || (!(cb_flag = atoi(argv[x]) & 0x1F00))){
cb_flag = 0;
outemsg(ERROR,CBINVALID);
}
} /* endif */
} /* endif */
if(!strcmp(argv[x],"/D")){
if (++x >= argc) {
outemsg(ERROR,DELAYINVALID);
} else {
delay = atoi(argv[x]); /* Save delay time */
} /* endif */
} /* endif */
if(!strcmp(argv[x],"/N")){
if ((++x >= argc) ||
(*argv[x]<'2') || (*argv[x]>'9')) { /* AUDIOx$ number */
outemsg(ERROR,NUMINVALID);
} else {
audioname[5] = *argv[x]; /* Copy number to our audio name */
} /* endif */
} /* endif */
if(!strcmp(argv[x],"/V")){
if (++x < argc) {
argint = strtoul(argv[x],&stopstring,10);
mastervol = 1;
devinfo.master_volume = (unsigned int)argint;
} /* endif */
} /* endif */
if(!strcmp(argv[x],"/M")){
if (++x < argc) {
monitor = atoi(argv[x]);
} /* endif */
} /* endif */
if(!strcmp(argv[x],"/I")){
not_picked_s = TRUE;
while (not_picked_s) {
outmsg(USERINPUT,INPMODE); /* what input should be used */
outmsg(HELP,INPUTLIST);
_setbkcolor(BLACK); /* draw a box for the user to */
/* enter the input */
_settextcolor(GRAY);
_settextposition(6,((short)(strlen(user_msg[INPMODE][1]))+5));
_outtext(" ");
_settextposition(6,((short)(strlen(user_msg[INPMODE][1]))+5));
if (read_kb(source_input_s,2) == 0) {
source_input = atoi(source_input_s);
if ((source_input > 12) || (source_input < 0)) {
outmsg(WARNING,INPINVALID);
} else {
not_picked_s = FALSE;
} /* endif */
}
} /* end while (not_picked_s) */
outmsg(ERROR,CLEARSCRN);
outmsg(HELP,CLEARSCRN);
} /* endif */
if(!strcmp(argv[x],"/O")){
not_picked_s = TRUE;
while (not_picked_s) {
outmsg(USERINPUT,OUTMODE); /* what input should be used */
outmsg(HELP,OUTPUTLIST);
_setbkcolor(BLACK); /* draw a box for the user to */
/* enter the input */
_settextcolor(GRAY);
_settextposition(6,((short)(strlen(user_msg[OUTMODE][1]))+5));
_outtext(" ");
_settextposition(6,((short)(strlen(user_msg[OUTMODE][1]))+5));
if (read_kb(source_output_s,2) == 0) {
source_output = atoi(source_output_s);
if ((source_output > 12) || (source_output < 0)) {
outmsg(WARNING,OUTINVALID);
} else {
not_picked_s = FALSE;
} /* endif */
}
} /* end while (not_picked_s) */
outmsg(ERROR,CLEARSCRN);
outmsg(HELP,CLEARSCRN);
} /* endif */
if(!strcmp(argv[x],"/S")){
supress = 1;
} /* endif */
if(!strcmp(argv[x],"/T")){
pos_flag = 1;
} /* endif */
if(!strcmp(argv[x],"/U")){
update_flag = 1;
} /* endif */
if(!strcmp(argv[x],"/W")){
audiowait = 1;
} /* endif */
if(!strcmp(argv[x],"/P")){
if (++x < argc) {
argint = strtoul(argv[x],&stopstring,10);
num_xbuffers_p = (unsigned int)argint;
xlength = 0;
for (sy=0; sy<num_xbuffers_p; sy++) {
if (++x < argc) {
argint = strtoul(argv[x],&stopstring,10);
if (argint > 65000) {
outemsg(ERROR,SIZEINVALID);
argint = 65000;
} /* endif */
xbuffer_len_p[sy] = (unsigned int)argint;
xlength += argint;
} else {
outemsg(ERROR,NOSIZE);
num_xbuffers_p = sy;
} /* endif */
} /* endfor */
} else {
outemsg(ERROR,NONUM);
} /* endif */
} /* endif */
if(!strcmp(argv[x],"/R")){
if (++x < argc) {
argint = strtoul(argv[x],&stopstring,10);
num_rbuffers_r = (unsigned int)argint;
rlength = 0;
for (sy=0; sy<num_rbuffers_r; sy++) {
if (++x < argc) {
argint = strtoul(argv[x],&stopstring,10);
if (argint > 65000) {
outemsg(ERROR,SIZEINVALID);
argint = 65000;
} /* endif */
rbuffer_len_r[sy] = (unsigned int)argint;
rlength += argint;
} else {
outemsg(ERROR,NOSIZE);
num_rbuffers_r = sy;
} /* endif */
} /* endfor */
} else {
outemsg(ERROR,NONUM);
} /* endif */
}
if(!strcmp(argv[x],"/B")){
batch = TRUE;
if (++x < argc) {
if(*argv[x]=='p' || *argv[x]=='P') { /* Get operation */
function = PLAY_DEMO; /* Copy number to our audio name */
if (++x < argc) {
strncpy(iname,argv[x],MAXSTRING); /* get filename to play */
} else {
outemsg(ERROR,BATCHNUMP);
return;
} /* endif */
} else if (*argv[x]=='r' || *argv[x]=='R') {
function = RCD_DEMO;
if (++x < argc) {
strncpy(iname,argv[x],MAXSTRING); /* get filename to play */
if (++x < argc) {
index = atoi(argv[x]);
if (index == 0) { /* MIDI */
mode = MIDI;
mode_i = 0;
channels = 0;
chan_i = NONE;
} else if (index < 5) { /* ADPCM */
mode = ADPCM;
channels = 1;
if (index == 1) {
mode_i = AVC_VOICE;
} else if (index == 2) {
mode_i = AVC_MUSIC;
} else if (index == 3) {
mode_i = AVC_STEREO;
channels = 2;
} else {
mode_i = AVC_HQ;
} /* endif */
} else if (index < 70) { /* PCM-MU_LAW-A_LAW */
if (index < 30) {
mode = PCM;
index -= 10;
} else if (index < 50) {
mode = MU_LAW;
index -= 30;
} else {
mode = A_LAW;
index -=50;
} /* endif */
if (index > 7) {
channels = 2;
index -= 8;
} else {
channels = 1;
} /* endif */
switch(index) {
default:
mode_i = PCM8k8b;
break;
case 1:
mode_i = PCM8k16b;
break;
case 2:
mode_i = PCM11k8b;
break;
case 3:
mode_i = PCM11k16b;
break;
case 4:
mode_i = PCM22k8b;
break;
case 5:
mode_i = PCM22k16b;
break;
case 6:
mode_i = PCM44k8b;
break;
case 7:
mode_i = PCM44k16b;
break;
} /* end switch */
if (mode == MU_LAW) {
mode_i += 11;
} else if (mode == A_LAW) {
mode_i += 15;
} /* endif */
} else if (index < 130) { /* M-Motion PCM-MU_LAW-A_LAW */
if (index < 80) {
mode = PCM;
index -= 70;
} else if (index < 100) {
mode = MU_LAW;
index -= 90;
} else {
mode = A_LAW;
index -=110;
} /* endif */
if (index > 5) {
channels = 2;
index -= 6;
} else {
channels = 1;
} /* endif */
switch(index) {
default:
mode_i = PCM7k8b;
break;
case 1:
mode_i = PCM7k16b;
break;
case 2:
mode_i = PCM315k8b;
break;
case 3:
mode_i = PCM315k16b;
break;
case 4:
mode_i = PCM48k8b;
break;
case 5:
mode_i = PCM48k16b;
break;
} /* end switch */
if (mode == MU_LAW) {
mode_i += 6;
} else if (mode == A_LAW) {
mode_i += 9;
} /* endif */
} else {
outemsg(ERROR,BATCHFUNC);
return;
} /* endif */
if (++x < argc) {
batch_time = atoi(argv[x]) * 1000;
} else {
/* make largest number possible so never reached */
batch_time = -1;
} /* endif */
} else {
outemsg(ERROR,BATCHNUMP);
return;
} /* endif */
} else {
outemsg(ERROR,BATCHNUMP);
return;
} /* endif */
} else {
outemsg(ERROR,BATCHFUNC);
return;
} /* endif */
} else {
outemsg(ERROR,BATCHNUMP);
return;
} /* endif */
} /* endif */
}
#if IS_OS2
rc = DosGetPID(&PidInfo);
rc = DosGetPrty(0,&priority,PidInfo.pid);
if (cb_flag) {
// if (rc = DosCreateSem(1,&callback,"\\sem\\demowait.sem")) {
if (rc = DosCreateSem(1,&callback,sem_name)) {
outemsg(ERROR,CREATESEM);
}
} /* endif */
#endif
/* Allocate the iobufs */
if ((xbuf = (struct iobuf far *)_fmalloc((size_t)(sizeof(struct iobuf)+
(num_xbuffers_p-1)*sizeof(struct addrs) ))) == NULL) {
outemsg(ERROR,MALLOCERR); /* Write failed return code */
restore(oldfgd,oldbgd,oldpos); /* exit demo program */
return;
}
if ((rbuf = (struct iobuf far *)_fmalloc((size_t)(sizeof(struct iobuf)+
(num_rbuffers_r-1)*sizeof(struct addrs) ))) == NULL) {
outemsg(ERROR,MALLOCERR); /* Write failed return code */
_ffree(xbuf);
restore(oldfgd,oldbgd,oldpos); /* exit demo program */
return;
}
#if 0
#if IS_DOS
if((audhndl = open(audioname,O_BINARY | O_RDWR)) == -1){
#else
if(rc = DosOpen(audioname,&audhndl,&ActionTaken,0l,0,1,0x0012,0l)){
#endif
outmsg(HELP,BLANK);
outmsg(HELP,NODDINSTAL); /* Display message on how to make sure*/
/* the device driver is installed */
_settextposition(9,((short)(strlen(help_msg[NODDINSTAL][0]))+5));
printf("%s",audioname);
outmsg(STATUS,EXITDEMO);
exit_ch = getch();
restore(oldfgd,oldbgd,oldpos); /* exit demo program */
_ffree(xbuf);
_ffree(rbuf);
return;
} /* endif rc = DosOpen */
#endif
do { /* until they want to exit */
user_esc = FALSE;
esc_count = 0;
runtotal = 0;
old_runtotal = 0;
playtotal = 0;
old_playtotal = 0;
okfile = FALSE; /* init flag to check if 'p' or 'r' entered*/
user_esc = FALSE; /* init exit flag to FALSE */
while (!okfile && !batch) {
outmsg(USERINPUT,PLAYRCD); /* Ask the user whether he wants to */
/* play a song or record one */
_settextposition(6,((short)(strlen(user_msg[PLAYRCD][1]))+5));
ch = getche();
outmsg(HELP,CLEARSCRN); /* Put out msg to user to tell them to */
if (ch == ESC) {
exit_ch = TRUE;
restore(oldfgd,oldbgd,oldpos); /* exit demo program */
_ffree(xbuf);
_ffree(rbuf);
return;
} /* endif ch = ESC */
if ((ch == play_file) || (ch == PLAY_FILE)) {
okfile = TRUE;
outmsg(TITLE,PLAYBACK); /* Write Playback Title to display */
inputmsgnum = PLAYFILE;
function = PLAY_DEMO;
} else if ((ch == rcd_file) || (ch == RCD_FILE)) {
okfile = TRUE;
outmsg(TITLE,RCD); /* Write Record Title to display */
inputmsgnum = RCDFILE;
function = RCD_DEMO;
} else {
outmsg(HELP,ENTERPR); /* Put out msg to user to tell them to */
/* enter a 'P' or 'R' */
} /* endif ch == R/P */
} /* end while (!okfile) */
okfile = FALSE; /* init flag to check if valid fname given */
while (!okfile) {
if (!batch) {
outmsg(USERINPUT,inputmsgnum);/* Write msg to get name of MIDI file */
/* to be played/created */
_setbkcolor(BLACK); /* draw a box for the user to enter fname */
_settextcolor(GRAY);
_settextposition(7,30);
_outtext(" ");
_settextposition(7,30); /* put cursor at beginning of box */
/* read the file to play from the screen*/
} /* endif */
if (!batch) {
if (read_kb(iname,MAXSTRING) != 0) {
user_esc = TRUE;
okfile = TRUE;
ch = ' ';
}
} /* endif */
if (!user_esc) {
strupr(iname);
/* Check to see if a filename was entered */
if ((iname==NULL) || (iname=="?")) {
if (function == PLAY_DEMO) {
outmsg(HELP,NOFNAMEP); /* put help info on screen for user */
} else { /* REC_DEMO */
outmsg(HELP,NOFNAMER); /* put help info on screen for user */
} /* endif function == PLAY_DEMO) */
} else { /* if filename was entered, then try and open the file */
if (function == PLAY_DEMO) {
/* Open input file */
if ((inhndl=open(iname,O_BINARY | O_RDONLY)) == -1) {
outmsg(ERROR,FILNOTFNDP); /* Put error msg up saying can't */
/* open the filename entered */
_settextposition(10,30); /* Write name of file to display */
printf("%s",iname);
outmsg(STATUS,EXITDEMO); /* Tell user to press key */
} else { /* file was found and opened successfully */
okfile = TRUE;
outmsg(YNQUEST,CLEARSCRN);
outmsg(WARNING,CLEARSCRN); /* Clear any warnings off */
} /* endif */
} else { /* RCD_DEMO */
not_picked = TRUE;
while (not_picked && !batch) {
outmsg(USERINPUT,PMODE); /* See what mode to use */
outmsg(HELP,MODEDEFS); /* List all the modes */
_setbkcolor(BLACK); /* draw a box for the user to */
/* enter the mode */
_settextcolor(GRAY);
_settextposition(7,30);
_outtext(" ");
_settextposition(7,30); /* put cur at beginning of box*/
/* read the mode */
not_picked = FALSE;
if (read_kb(mode_s,10) == 0) {
ch = ' ';
strupr(mode_s);
if ((!(strncmp(mode_s,"PCM",3))) ||
(!(strncmp(mode_s,"MU_LAW",6))) ||
(!(strncmp(mode_s,"A_LAW",5)))) {
if (!(strncmp(mode_s,"PCM",3))) mode = PCM;
if (!(strncmp(mode_s,"MU_LAW",6))) mode = MU_LAW;
if (!(strncmp(mode_s,"A_LAW",5))) mode = A_LAW;
not_picked_s = TRUE;
outmsg(WARNING,CLEARSCRN);
while (not_picked_s) {
outmsg(USERINPUT,PCMMODES); /* what rate/bit count to use */
if (mode == PCM) {
outmsg(HELP,MODEPCM); /* List all the rates/counts */
} else { /* MU_LAW or A_LAW */
outmsg(HELP,MODELAW); /* List all the rates/counts */
} /* endif */
_setbkcolor(BLACK); /* draw a box for the user to */
/* enter the rate/count */
_settextcolor(GRAY);
_settextposition(7,((short)(strlen(user_msg[PCMMODES][1]))+5));
_outtext(" ");
_settextposition(7,((short)(strlen(user_msg[PCMMODES][1]))+5));
/* read the mode */
not_picked_s = FALSE;
if (read_kb(rate_s,8) == 0) {
ch = ' ';
strupr(rate_s);
if (!(strncmp(rate_s,"8K8S",4))) {
mode_i = PCM8k8b;
channels = 2;
} else if (!(strncmp(rate_s,"11K8S",5))) {
mode_i = PCM11k8b;
channels = 2;
} else if (!(strncmp(rate_s,"22K8S",5))) {
mode_i = PCM22k8b;
channels = 2;
} else if (!(strncmp(rate_s,"44K8S",5))) {
mode_i = PCM44k8b;
channels = 2;
} else if (!(strncmp(rate_s,"8K8",3))) {
mode_i = PCM8k8b;
channels = 1;
} else if (!(strncmp(rate_s,"11K8",4))) {
mode_i = PCM11k8b;
channels = 1;
} else if (!(strncmp(rate_s,"22K8",4))) {
mode_i = PCM22k8b;
channels = 1;
} else if (!(strncmp(rate_s,"44K8",4))) {
mode_i = PCM44k8b;
channels = 1;
} else if (mode == PCM) {
if (!(strncmp(rate_s,"8K16S",5))) {
mode_i = PCM8k16b;
channels = 2;
} else if (!(strncmp(rate_s,"11K16S",6))) {
mode_i = PCM11k16b;
channels = 2;
} else if (!(strncmp(rate_s,"22K16S",6))) {
mode_i = PCM22k16b;
channels = 2;
} else if (!(strncmp(rate_s,"44K16S",6))) {
mode_i = PCM44k16b;
channels = 2;
} else if (!(strncmp(rate_s,"8K16",4))) {
mode_i = PCM8k16b;
channels = 1;
} else if (!(strncmp(rate_s,"11K16",5))) {
mode_i = PCM11k16b;
channels = 1;
} else if (!(strncmp(rate_s,"22K16",5))) {
mode_i = PCM22k16b;
channels = 1;
} else if (!(strncmp(rate_s,"44K16",5))) {
mode_i = PCM44k16b;
channels = 1;
} else { /* not recognized/supported */
not_picked_s = TRUE;
outmsg(WARNING,NORATE);
} /* endif */
} else { /* not recognized/supported */
not_picked_s = TRUE;
outmsg(WARNING,NORATE);
} /* endif */
if (mode == MU_LAW) {
mode_i += 11;
} else if (mode == A_LAW) {
mode_i += 15;
} /* endif */
} else {
ch = ESC;
} /* endif ch != ESC */
} /* end while (not_picked_s) */
} else if (!(strncmp(mode_s,"ADPCM",5))) {
mode = ADPCM;
not_picked_s = TRUE;
outmsg(WARNING,CLEARSCRN);
while (not_picked_s) {
outmsg(USERINPUT,AVCMODES); /* what rate/bit count to use */
outmsg(HELP,MODEAVC); /* List all the rates/counts */
_setbkcolor(BLACK); /* draw a box for the user to */
/* enter the rate/count */
_settextcolor(GRAY);
_settextposition(7,30);
_outtext(" ");
_settextposition(7,30); /* put cur at beginning of box*/
not_picked_s = FALSE;
if (read_kb(rate_s,8) == 0) {
ch = ' ';
strupr(rate_s); /* convert mode to UPPERCASE */
if (!(strncmp(rate_s,"VOICE",5))) {
mode_i = AVC_VOICE;
channels = 1;
} else if (!(strncmp(rate_s,"MUSIC",5))) {
mode_i = AVC_MUSIC;
channels = 1;
} else if (!(strncmp(rate_s,"STEREO",6))) {
mode_i = AVC_STEREO;
channels = 2;
} else if (!(strncmp(rate_s,"HQ",2))) {
mode_i = AVC_HQ;
channels = 1;
} else { /* not recognized/supported */
not_picked_s = TRUE;
outemsg(WARNING,NOADPCM);
} /* end if rate_s */
} else {
ch = ESC;
} /* endif */
} /* end while (not_picked_s) */
} else if (!(strncmp(mode_s,"CVSD",4))) {
mode = CVSD;
not_picked_s = TRUE;
outmsg(WARNING,CLEARSCRN);
while (not_picked_s) {
outmsg(USERINPUT,CVSDMODES); /* what rate/bit count to use */
outmsg(HELP,MODECVSD); /* List all the rates/counts */
_setbkcolor(BLACK); /* draw a box for the user to */
/* enter the rate/count */
_settextcolor(GRAY);
_settextposition(7,30);
_outtext(" ");
_settextposition(7,30); /* put cur at beginning of box*/
not_picked_s = FALSE;
if (read_kb(rate_s,1) == 0) {
ch = ' ';
strupr(rate_s); /* convert mode to UPPERCASE */
if (!(strncmp(rate_s,"0",1))) {
mode_i = CVSD_0;
} else if (!(strncmp(rate_s,"1",1))) {
mode_i = CVSD_1;
} else if (!(strncmp(rate_s,"2",1))) {
mode_i = CVSD_2;
} else if (!(strncmp(rate_s,"3",1))) {
mode_i = CVSD_3;
} else if (!(strncmp(rate_s,"4",1))) {
mode_i = CVSD_4;
} else if (!(strncmp(rate_s,"5",1))) {
mode_i = CVSD_5;
} else { /* not recognized/supported */
not_picked_s = TRUE;
outemsg(WARNING,NOCVSD);
} /* end if rate_s */
channels = 1;
} else {
ch = ESC;
} /* endif */
} /* end while (not_picked_s) */
} else if (!(strncmp(mode_s,"MIDI",4))) {
mode = MIDI;
mode_i = 0;
channels = 0;
chan_i = NONE;
outmsg(WARNING,CLEARSCRN);
} else { /* not recognized/supported */
not_picked = TRUE;
outmsg(WARNING,NOMODE);
} /* endif mode_s == */
} else {
ch = ESC;
} /* endif ch != ESC */
} /* endwhile not_picked */
outmsg(USERINPUT,CLEARSCRN);
outmsg(HELP,CLEARSCRN);
outmsg(WARNING,CLEARSCRN);
if (ch != ESC) {
/* Open output file */
if(!(inhndl=open(iname,O_BINARY | O_WRONLY | O_CREAT
| O_TRUNC,S_IWRITE))==-1) {
outmsg(ERROR,FILNOTFNDR); /* Put error msg up saying can't */
/* open the filename entered */
_settextposition(10,30); /* Write name of file to display */
printf("%s",iname);
outmsg(STATUS,CONTINUE); /* Tell user to press key */
getch();
} else { /* file was opened successfully */
okfile = TRUE;
} /* endif */
} /* endif ch != ESC */
} /* endif function == PLAY_DEMO */
} /* endif */
} /* endif */
} /* endwhile */
outmsg(STATUS,CLEARSCRN); /* clear status and error */
outmsg(ERROR,CLEARSCRN); /* messages */
if (!user_esc) {
#if IS_DOS
if((audhndl = open(audioname,O_BINARY | O_RDWR)) == -1){
#else
if(rc = DosOpen(audioname,&audhndl,&ActionTaken,0l,0,1,0x0012,0l)){
#endif
outmsg(HELP,BLANK);
outmsg(HELP,NODDINSTAL); /* Display message on how to make sure*/
/* the device driver is installed */
_settextposition(9,((short)(strlen(help_msg[NODDINSTAL][0]))+5));
printf("%s",audioname);
outmsg(STATUS,EXITDEMO);
exit_ch = getch();
restore(oldfgd,oldbgd,oldpos); /* exit demo program */
_ffree(xbuf);
_ffree(rbuf);
return;
} /* endif rc = DosOpen */
rbuffer = 0;
xbuffer = 0;
old_segnum = 0;
available_buffs = 0;
update_segnum = 0;
update_cnt = 0;
update_size = 0;
rtn_segnum = 0;
if (function == PLAY_DEMO) {
if (update_flag && (num_xbuffers_p < 3)) {
outemsg(ERROR,EUPDATEINVALID);
} /* endif */
rc = audplay();
} else { /* RCD_DEMO */
if (update_flag) {
outemsg(ERROR,EUPDATEWREC);
} /* endif */
rc = audrec();
} /* endif function == PLAY_DEMO */
close(inhndl); /* close the MIDI standard file */
close(audhndl);
if (!rc) freebuffs(xbuf->num_buffers,rbuf->num_buffers);
outmsg(WARNING,CLEARSCRN);
outmsg(STATUS,EXITDEMO); /* write message to exit program */
if (kbhit()) {
ch = getch(); /* wait for a key to be pressed before exiting*/
} /* endif */
} else {
outmsg(USERINPUT,CLEARSCRN);
} /* endif */
} while ((ch != ESC) && (!exit_ch) && !batch);
// close(audhndl);
restore(oldfgd,oldbgd,oldpos); /* restore original screen colors */
_ffree(xbuf);
_ffree(rbuf);
} /* end main */
/*****************************************************************************/
/* */
/* FUNCTION NAME = restore */
/* */
/* FUNCTION = restores the original display colors and cursor position */
/* */
/* INPUT PARAMETERS = oldfgd - original foreground color */
/* oldbgd - original background color */
/* oldpos - original cursor position */
/* */
/* RETURN CODE = none */
/* */
/*****************************************************************************/
void restore(short oldfgd, long oldbgd, struct rccoord oldpos)
{
/* Restore original foreground and background and cursor positions */
_settextcolor(oldfgd);
_setbkcolor(oldbgd);
_clearscreen(_GCLEARSCREEN);
_settextposition(oldpos.row, oldpos.col);
#if IS_OS2
if (cb_flag) {
if (rc = DosCloseSem(callback)) {
outemsg(ERROR,CLOSESEM);
}
} /* endif */
#endif
} /* end restore() */
/*****************************************************************************/
/* */
/* FUNCTION NAME = audrec */
/* */
/* FUNCTION = record input data to the output file */
/* */
/* INPUT PARAMETERS = none */
/* */
/* RETURN CODE = 0 Successful */
/* 1 Failure */
/* */
/*****************************************************************************/
int audrec(void)
{
/*****************************************************************************/
/* LOCAL VARIABLE DEFINITIONS */
/*****************************************************************************/
int ch;
int x;
int i;
char wasor = 0;
unsigned long readsize;
struct audio_control control;
struct audio_change change;
struct audio_hpi hpi;
char wrap_it;
unsigned long f8_count=0; /* count of F8's broken off in last buffer*/
/* passed to seq2midi routine */
/* Setup our own xbuffer */
if ((xbuffer = (char far *)_fmalloc((size_t)XBUFFERSIZER))==NULL) {
outemsg(ERROR,MALLOCERR); /* Write failed return code */
close(audhndl);
close(inhndl);
freebuffs(1,0);
return(1);
}
xbuf->size = XBUFFERSIZER;
xbuf->num_buffers = 1;
xbuf->buf[0].Virt = xbuffer;
xbuf->buf[0].length = XBUFFERSIZER;
xbuf->head = xbuffer;
xbuf->tail = xbuffer;
xbuf->count = 0;
xbuf->runflags = 0;
for (sy=0; sy<num_rbuffers_r; sy++) {
if ((rbuffer = (char far *)_fmalloc((size_t)rbuffer_len_r[sy]))==NULL) {
outemsg(ERROR,MALLOCERR); /* Write failed return code */
close(audhndl);
close(inhndl);
freebuffs(1,sy);
return(1);
}
rbuf->buf[sy].Virt = rbuffer;
rbuf->buf[sy].length = rbuffer_len_r[sy];
} /* endfor */
rbuf->size = rlength;
rbuf->num_buffers = num_rbuffers_r;
rbuf->head = rbuf->buf[0].Virt;
rbuf->tail = rbuf->buf[0].Virt;
rbuf->count = 0;
rbuf->runflags = cb_flag;
rbuf->position = 0;
hpi.cb = NULL;
hpi.newxbuf = xbuf;
hpi.newrbuf = rbuf;
hpi.flags = 0;
#if IS_DOS
if(rc = ioctl(&hpi,AUDIO_HPI,audhndl)){
#else
if(rc = DosDevIOCtl(&hpi, NULL, 0x40+AUDIO_HPI, 0x80, audhndl)) {
#endif
outmsg(ERROR,HPIIOCTL); /* Write failed return code */
_settextposition(11,30);
printf("%i",rc);
endemsg(ERROR);
close(audhndl);
close(inhndl);
freebuffs(xbuf->num_buffers,rbuf->num_buffers);
return(1);
}
#if IS_DOS
direct_call = hpi.ep;
#endif
/**************************************************************************/
/* Issue INIT IOCtl */
/**************************************************************************/
init.mode = mode;
init.flags = mode_table[mode_i].flags;
init.srate = mode_table[mode_i].srate_low;
init.bits_per_sample = mode_table[mode_i].bps_low;
init.bsize = mode_table[mode_i].bsize;
init.channels = channels;
if (channels == 1) {
chan_i = MONO;
} else {
chan_i = STEREO;
} /* endif */
init.operation = RECORD;
init.rc = 0;
init.reserved = NULL;
init.version_level = CURRENT_VERSION;
#if IS_DOS
if(direct_call == NULL){
rc = ioctl(&init,AUDIO_INIT,audhndl);
}else{
rc = (*direct_call)(EP_INIT,(char far *)&init,23);
}
if (rc) {
#else
if(rc = DosDevIOCtl(&init, NULL, 0x40+AUDIO_INIT, 0x80, audhndl)) {
#endif
outmsg(ERROR,EINITIOCTL);
_settextposition(11,30);
printf("%i",rc);
endemsg(ERROR);
close(audhndl);
close(inhndl);
freebuffs(xbuf->num_buffers,rbuf->num_buffers);
return(1);
}
if (init.flags & BESTFIT_PROVIDED) {
mode = init.mode;
channels = init.channels;
outemsg(WARNING,BESTFIT);
}
/***************************************************************************/
/* Load code module */
/***************************************************************************/
if (init.flags & LOAD_CODE) { /* Load DSP code module */
if (rc = dspload(&init.loadpath[0], audhndl)) {
outmsg(ERROR,EDSPLOAD); /* Write failed return code */
_settextposition(11,30);
printf("%i",rc);
endemsg(ERROR);
close(audhndl);
close(inhndl);
freebuffs(xbuf->num_buffers,rbuf->num_buffers);
return(1);
}
} /* endif LOAD_CODE */
if (init.rc != 0) {
outmsg(ERROR,INITFAILED); /* Write failed return code */
_settextposition(11,30);
printf("%i",init.rc);
endemsg(ERROR);
} /* endif (rc != 0 ) */
/* Issue CHANGE IOCtl */
control.position = 0; /* Do it now */
control.ioctl_request = AUDIO_CHANGE; /* Change configuration */
control.return_code = 0; /* zero out return code field */
control.request_info = &change; /* Request data = change struct*/
change.input_list[0].devtype = source_input;
change.input_list[0].devnum = DEVICE_1;
change.output_list[0].devtype = source_output;
change.output_list[0].devnum = DEVICE_1;
change.input_list[1].devtype = NULL_INPUT;
change.input_list[1].devnum = DEVICE_1;
change.output_list[1].devtype = NULL_OUTPUT;
change.output_list[1].devnum = DEVICE_1;
change.input = INPUTS_LISTED;
change.output = OUTPUTS_LISTED; /* Output select */
change.monitor = monitor; /* Monitor */
change.volume = 0x7fffffff; /* Volume set to maximum */
change.volume_delay = delay; /* Set volume now */
change.balance = 0x3fffffff; /* Balance set to mid-point */
change.balance_delay = delay; /* Set balance now */
change.treble = 0x3fffffff; /* Mid point */
change.bass = 0x3fffffff; /* Mid point */
change.pitch = 0; /* */
if (mastervol) {
change.dev_info = &devinfo; /* Device dependent data */
} else {
change.dev_info = NULL; /* No device dependent data */
}
change.input_gain = 0; /* No input gain */
change.mode_info = NULL; /* No mode dependent data */
#if IS_DOS
if(direct_call == NULL){
rc = ioctl(&control,AUDIO_CONTROL,audhndl);
}else{
rc = (*direct_call)(EP_CONTROL,(char far *)&control,23);
}
/*************************************************************************/
/* Issue IOCTL set device parameters to force BINARY mode (otherwise an */
/* 0x1a read will cause DOS to assume EOF) You might need to uncomment */
/* this if you want to build a DOS only version. */
/*************************************************************************/
dosregs.x.ax = 0x4401;
dosregs.x.bx = audhndl;
dosregs.x.dx = 0x00a0;
intdos(&dosregs, &dosregs);
if (rc) {
#else
if(rc = DosDevIOCtl(&control, NULL, 0x40+AUDIO_CONTROL, 0x80, audhndl)) {
#endif
outmsg(ERROR,ECHNGIOCTL);
_settextposition(11,30);
printf("%i",rc);
endemsg(ERROR);
close(audhndl);
close(inhndl);
freebuffs(xbuf->num_buffers,rbuf->num_buffers);
return(1);
}
/**************************************************************************/
if (init.mode == MIDI) {
if (write_midi_headers()){
freebuffs(xbuf->num_buffers,rbuf->num_buffers);
return(1);
}
} else { /* RIFF mode */
rc = write_riff_headers();
} /* endif MIDI mode */
outmsg(HELP,BLANK);
outmsg(HELP,RECORD1);
_settextposition(10,((short)(strlen(help_msg[RECORD1][1]))+5));
printf("%s - %s %s",iname,file_type_msg[mode_i],mono_stereo_msg[chan_i]);
_settextposition(11,((short)(strlen(help_msg[RECORD1][2]))+5));
printf("%s",audioname);
if (pos_flag) {
_settextposition(12,5);
_setbkcolor(AQUA); /* Set background color */
_settextcolor(BLACK); /* Set foreground/text color */
_outtext(extra_msg[POSITION]);
} /* endif */
if (cb_flag) {
_settextposition(17,5);
_setbkcolor(AQUA); /* Set background color */
_settextcolor(BLACK); /* Set foreground/text color */
_outtext(extra_msg[CBCOUNT]);
} /* endif */
outmsg(STATUS,STARTSTOP);
started = 0;
x = 0;
running_status = 0; /* init to no running status */
last_data_bytes = 0;
data_bytes = 0; /* init number of data bytes */
/* expected to none */
delta_time = FALSE;
old_segnum = 0;
do {
/***********************************************************************/
/* See how much data is available from the MIDI queue */
/***********************************************************************/
if (user_esc) {
readsize = esc_count;
} else {
readsize = rbuf->count;
} /* endif */
if(readsize > 0x7ffe) readsize = 0x7ffe; /* Limit to int range */
/* Don't allow write to wrap around the buffer */
if(readsize >= (unsigned long)((rbuf->buf[rbuf->tail_segnum].Virt-rbuf->tail)
+rbuf->buf[rbuf->tail_segnum].length)){
readsize = (unsigned long)((rbuf->buf[rbuf->tail_segnum].Virt-rbuf->tail)
+rbuf->buf[rbuf->tail_segnum].length);
wrap_it = TRUE;
} else {
wrap_it = FALSE;
}
if (readsize > 0) {
if (init.mode == MIDI) { /* MIDI data to record? */
if (readsize > 512) readsize = 512;
runtotal += readsize;
/********************************************************************/
/* Convert data to MIDI standard format and write to file */
/********************************************************************/
i = seq2midi(rbuf->tail,(int)readsize,&f8_count);
} else { /* RIFF file being created */
runtotal += readsize;
/* Write out the buffer */
i = write(inhndl,(char *)rbuf->tail,(unsigned)readsize);
if (i != (int)readsize) {
outmsg(ERROR,DISKFULL);
_settextposition(10,30);
printf("%s", iname);
endemsg(ERROR);
freebuffs(xbuf->num_buffers,rbuf->num_buffers);
return (1);
} /* if ndata = -1 */
} /* endif */
if (user_esc) {
esc_count -= i;
} /* endif */
if (wrap_it) {
if (++rbuf->tail_segnum >= num_rbuffers_r) {
rbuf->tail_segnum = 0;
} /* endif */
rbuf->tail = rbuf->buf[rbuf->tail_segnum].Virt;
} else {
rbuf->tail += i;
} /* endif */
rbuf->runflags |= IOBUF_LOCK;
rbuf->count -= i;
rbuf->runflags &= ~IOBUF_LOCK;
} /* endif readsize > 0 */
if (batch) {
if (rbuf->position) {
if (rbuf->position >= batch_time) {
rbuf->runflags &= ~STARTED;
esc_count = rbuf->count;
user_esc = TRUE;
started = 1;
} /* endif */
} else {
rbuf->runflags |= STARTED;
started = 1;
strcpy(status,"Running ");
} /* endif */
} /* endif */
/**************************/
/* Process keyboard input */
/**************************/
if (kbhit()) {
ch=getch();
switch(ch){
case ' ':
if (!started) { /* If not started, issue START*/
started = 1;
rbuf->runflags |= STARTED;
strcpy(status,"Running ");
} else if (started==1) { /* If running, issue PAUSE */
started=2;
rbuf->runflags |= PAUSED;
strcpy(status,"Paused ");
} else { /* if paused, issue RESUME */
started = 1;
rbuf->runflags &= ~PAUSED;
strcpy(status,"Resumed ");
}
break;
case 'L':
case 'l':
cur_input = LEFT_LINE_INPUT;
change_settings();
break;
case 'R':
case 'r':
cur_input = RIGHT_LINE_INPUT;
change_settings();
break;
case 'S':
case 's':
cur_input = STEREO_LINE_INPUT;
change_settings();
break;
case 'M':
case 'm':
cur_input = MIC_INPUT;
change_settings();
break;
case '0':
monitor = 0;
change_settings();
break;
case '1':
monitor = 1;
change_settings();
break;
case '3':
monitor = 3;
change_settings();
break;
case 'B':
case 'b':
cur_input = BOOSTED_MIC_INPUT;
change_settings();
break;
case ESC: /* Esc = quit */
rbuf->runflags &= ~STARTED;
esc_count = rbuf->count;
user_esc = TRUE;
started = 1;
break;
default:
break;
} /* end switch */
_settextposition(13,((short)(strlen(help_msg[RECORD1][4]))+5));
printf("%s",status);
} /* endif */
if (rbuf->runflags & IOB_OVERRUN) {
wasor = 1;
outmsg(WARNING,OVERRUN);
rbuf->runflags &= ~IOB_OVERRUN;
} else if (wasor) {
wasor = 0;
outmsg(WARNING,CLEARSCRN);
} /* endif */
if (!supress) {
if (old_runtotal != runtotal) {
old_runtotal = runtotal;
_settextposition(15,((short)(strlen(help_msg[RECORD1][6]))+5));
printf("%6.6ld",runtotal);
if (pos_flag) {
_settextposition(12,((short)(strlen(extra_msg[POSITION]))+5));
printf("%6.6ld",rbuf->position);
} /* endif */
if (cb_flag) {
_settextposition(17,((short)(strlen(extra_msg[CBCOUNT]))+5));
printf("%6.6ld",interrupt_count);
} /* endif */
} /* endif */
} /* endif */
} while ((user_esc == FALSE) ||
((user_esc == TRUE) && (esc_count > 0)));
rbuf->runflags |= IOBUF_LOCK;
rbuf->count = 0;
rbuf->tail_segnum = 0;
rbuf->head = rbuf->tail = rbuf->buf[0].Virt;
rbuf->runflags &= ~IOBUF_LOCK;
if (init.mode == MIDI) { /* MIDI file being created ? */
rc = write_midi_lengths();
} else { /* RIFF format needed */
rc = write_riff_lengths();
} /* endif MIDI file being created */
outmsg(HELP,BLANK);
return (0);
} /* end audrec */
/*****************************************************************************/
/* */
/* FUNCTION NAME = write_riff_headers */
/* */
/* FUNCTION = write RIFF chunk headers */
/* */
/* INPUT PARAMETERS = none */
/* */
/* RETURN CODE = 0 Successful */
/* 1 Failure */
/* */
/*****************************************************************************/
int write_riff_headers(void) /* Begin Function */
{
/*****************************************************************************/
/* LOCAL VARIABLE DEFINITIONS */
/*****************************************************************************/
unsigned int ndata;
struct waveformat_s {
unsigned int formattag; /* format category */
unsigned int nchannels; /* number of channels */
unsigned long nsamplespersec; /* sampling rate */
unsigned long navgbytespersec; /* for buffering */
unsigned int nblockalign; /* block alignment */
unsigned int nbitspersample; /* sample size */
} waveformat;
/* Write out 'RIFF' and dummy length */
if ((ndata = (unsigned)write(inhndl,(char *)RIFF_header,8)) == 8) {
/* Write out 'WAVE' or 'ibmw' */
if (mode == CVSD) {
ndata = (unsigned)write(inhndl,(char *)ibmw_header,4);
} else {
ndata = (unsigned)write(inhndl,(char *)WAVE_header,4);
} /* endif */
if (ndata == 4) {
/* Write out 'fmt ' and dummy length */
if ((ndata = (unsigned)write(inhndl,(char *)fmt_header,8)) == 8) {
switch (mode) {
case PCM:
waveformat.formattag = 1; /* format category */
break;
case MU_LAW:
waveformat.formattag = 0x0101;
break;
case A_LAW:
waveformat.formattag = 0x0102;
break;
case ADPCM:
waveformat.formattag = 0x0103;
break;
case CVSD:
waveformat.formattag = 5;
break;
} /* end switch */
waveformat.nchannels = channels; /* number of channels*/
waveformat.nsamplespersec = init.srate; /* sampling rate */
/* sample size*/
waveformat.nbitspersample = (int)init.bits_per_sample;
waveformat.nblockalign = waveformat.nchannels /* block alignment */
* (waveformat.nbitspersample / 8);
/* avg bytes/sec */
waveformat.navgbytespersec = waveformat.nchannels * waveformat.nsamplespersec
* (waveformat.nbitspersample / 8);
/* Write out wave format structure */
if ((ndata = (unsigned)write(inhndl,(char *)&waveformat,16)) == 16) {
/* Write out 'data' and dummy length */
if ((ndata = (unsigned)write(inhndl,(char *)data_header,8)) == 8) {
return(0); /* return successfully */
} /* endif */
} /* endif */
} /* endif */
} /* endif */
} /* endif */
/* if got to here then we failed somewhere - report error */
outmsg(HELP,CLEARSCRN);
outmsg(ERROR,DISKFULL);
_settextposition(10,30);
printf("%s", iname);
endemsg(ERROR);
return (1);
} /* end write_riff_headers() */
/*****************************************************************************/
/* */
/* FUNCTION NAME = write_midi_headers */
/* */
/* FUNCTION = write HEADER Chunk and beginning of TRACK chunk to file */
/* */
/* INPUT PARAMETERS = none */
/* */
/* RETURN CODE = 0 Successful */
/* 1 Failure */
/* */
/*****************************************************************************/
int write_midi_headers(void) /* Begin Function */
{
/*****************************************************************************/
/* LOCAL VARIABLE DEFINITIONS */
/*****************************************************************************/
char tpqn_s[3]; /* string value of tpqn */
int ch;
int tpqn; /* int value for tpqn */
int tpqn_not_valid;
int ndata;
unsigned long tttttt; /* tempo - beats per minute */
tpqn_not_valid = TRUE;
while (tpqn_not_valid) {
/* Ask the user how many ticks per quarter - default 120 */
outmsg(USERINPUT,TPQN); /* Write msg to get the tpqn to use */
_setbkcolor(BLACK); /* draw a box for the user to enter tpqn */
_settextcolor(GRAY);
_settextposition(7,30);
_outtext(" ");
_settextposition(7,30); /* put cursor at beginning of box */
_settextposition(7,30); /* put cursor at beginning of box */
/* read the tpqn value from the screen */
if (read_kb(tpqn_s,3) == 0) {
outmsg(USERINPUT,CLEARSCRN); /* Clear the screen */
tpqn = atoi(tpqn_s); /* convert string to integer */
switch(tpqn) {
case 48: /* check to see that multiple of 24 */
case 72:
case 96:
case 120:
case 144:
case 168:
case 192:
case 216:
case 240:
case 264:
case 288:
case 312:
case 336:
case 360:
case 384:
tpqn_not_valid = FALSE;
break;
default:
outmsg(WARNING,TPQNVAL); /* not a valid value - give 'em help */
break;
} /* end switch(tpqn) */
} else {
ch = ESC;
return(-1);
} /* endif ch != ESC */
} /* endwhile */
outmsg(WARNING,CLEARSCRN); /* clear any warning message that may */
/* have been displayed */
/* put requested counts into timinit to tell the device driver and also */
/* save it in the header chunk for the MIDI file. */
timinitr[7] = (unsigned char)((tpqn / 24)-1);
header[12] = (char)(tpqn & 0xFF00);
header[13] = (char)(tpqn & 0xFF);
/**************************************************************************/
/* Enable timing data and ppqn - would only get here if MIDI mode */
/**************************************************************************/
dcwrite(timinitr,10,1);
outmsg(USERINPUT,CLEARSCRN);
/**************************************************************************/
/* Write out Header Chunk */
/**************************************************************************/
if ((ndata = (unsigned)write(inhndl,(char *)header,14)) != 14) {
outmsg(HELP,CLEARSCRN);
outmsg(ERROR,DISKFULL);
_settextposition(10,30);
printf("%s", iname);
endemsg(ERROR);
return (1);
} /* endif fwrite */
/**************************************************************************/
/* Write out Track Chunk */
/**************************************************************************/
if ((ndata = (unsigned)write(inhndl,(char *)track,8)) != 8) {
outmsg(HELP,CLEARSCRN);
outmsg(ERROR,DISKFULL);
_settextposition(10,30);
printf("%s", iname);
endemsg(ERROR);
return (1);
} /* endif fwrite */
/* Write MEDA event to set tempo */
/* calculate the times per beat */
tttttt = 600000000 / ((tpqn*10) & 0x3FFF);
/* put result into conv_buf */
tempo_meda[6] = (unsigned char)(tttttt & 0x000000FF);
tempo_meda[5] = (unsigned char)((tttttt >> 8) & 0x000000FF);
tempo_meda[4] = (unsigned char)((tttttt >> 16) & 0x000000FF);
if ((ndata = (unsigned)write(inhndl,(char *)tempo_meda,7)) != 7) {
outmsg(HELP,CLEARSCRN);
outmsg(ERROR,DISKFULL);
_settextposition(10,30);
printf("%s", iname);
endemsg(ERROR);
return (1);
} /* endif fwrite */
return (0);
} /* end write_midi_headers */
/*****************************************************************************/
/* */
/* FUNCTION NAME = write_riff_lengths */
/* */
/* FUNCTION = write RIFF chunk lengths */
/* */
/* INPUT PARAMETERS = none */
/* */
/* RETURN CODE = 0 Successful */
/* 1 Failure */
/* */
/*****************************************************************************/
int write_riff_lengths(void) /* Begin Function */
{
/*****************************************************************************/
/* LOCAL VARIABLE DEFINITIONS */
/*****************************************************************************/
unsigned long chunk_len=0; /* length of chunk */
/* determine length of data chunk = */
/* Position file length */
/* 0 - RIFF chunk ID (4 bytes) */
/* 4 - chunk length (4 bytes) */
/* 8 - WAVE chunk ID (4 bytes) */
/* 12 - fmt chunk ID (4 bytes) */
/* 16 - chunk length (4 bytes) */
/* 20 - waveformat structure (16 bytes) */
/* 36 - data chunk id (4 bytes) */
/* 40 - chunk length (4 bytes) */
/* write RIFF chunk length to file */
chunk_len = filelength(inhndl) - 8;
/* Position marker to data chunk length in file */
lseek(inhndl,4,SEEK_SET);
if ((unsigned)write(inhndl,(char *)&chunk_len,4) != 4) {
outmsg(HELP,CLEARSCRN);
outmsg(ERROR,DISKFULL);
_settextposition(10,30);
printf("%s", iname);
endemsg(ERROR);
return (1);
} /* endif write */
/* write 'data' chunk length to file */
chunk_len -= 36; /* WAVE and length shorter than WAVE chunk & fmt chunk*/
/* Position marker to data chunk length in file */
lseek(inhndl,40,SEEK_SET);
if ((unsigned)write(inhndl,(char *)&chunk_len,4) != 4) {
outmsg(HELP,CLEARSCRN);
outmsg(ERROR,DISKFULL);
_settextposition(10,30);
printf("%s", iname);
endemsg(ERROR);
return (1);
} /* endif write */
/* write 'fmt ' chunk length to file */
chunk_len = 16; /* WAVE and length shorter than WAVE chunk */
/* Position marker to data chunk length in file */
lseek(inhndl,16,SEEK_SET);
if ((unsigned)write(inhndl,(char *)&chunk_len,4) != 4) {
outmsg(HELP,CLEARSCRN);
outmsg(ERROR,DISKFULL);
_settextposition(10,30);
printf("%s", iname);
endemsg(ERROR);
return (1);
} /* endif write */
return(0);
} /* end write_riff_lengths() */
/*****************************************************************************/
/* */
/* FUNCTION NAME = write_midi_lengths */
/* */
/* FUNCTION = write MIDI track lengths and ending meda events */
/* */
/* INPUT PARAMETERS = none */
/* */
/* RETURN CODE = 0 Successful */
/* 1 Failure */
/* */
/*****************************************************************************/
int write_midi_lengths(void) /* Begin Function */
{
/*****************************************************************************/
/* LOCAL VARIABLE DEFINITIONS */
/*****************************************************************************/
int ndata;
unsigned long chunk_len=0; /* length of chunk */
/***********************************************************************/
/* Write out End of Track MEDA event */
/***********************************************************************/
if ((ndata = (unsigned)write(inhndl,(char *)eot_meda,4)) != 4) {
outmsg(HELP,CLEARSCRN);
outmsg(ERROR,DISKFULL);
_settextposition(10,30);
printf("%s", iname);
endemsg(ERROR);
return (1);
} /* endif fwrite */
/* determine length of track chunk = */
/* file length */
/* - header chunk (14 bytes) */
/* - track chunk first 8 bytes */
chunk_len = filelength(inhndl) - 14 - 8;
track[7] = (unsigned char)(chunk_len & 0xFF);
chunk_len >>= 8;
track[6] = (unsigned char)(chunk_len & 0xFF);
chunk_len >>= 8;
track[5] = (unsigned char)(chunk_len & 0xFF);
chunk_len >>= 8;
track[4] = (unsigned char)(chunk_len & 0xFF);
lseek(inhndl,14,SEEK_SET); /* Go to the beginning of the file */
/* to write in length of the track */
/* chunk. */
/***********************************************************************/
/* Write out Track Chunk */
/***********************************************************************/
if ((ndata = (unsigned)write(inhndl,(char *)track,8)) != 8) {
outmsg(HELP,CLEARSCRN);
outmsg(ERROR,DISKFULL);
_settextposition(10,30);
printf("%s", iname);
endemsg(ERROR);
return (1);
} /* endif write */
return(0);
} /* end write_midi_lengths() */
/*****************************************************************************/
/* */
/* FUNCTION NAME = audplay */
/* */
/* FUNCTION = play file */
/* */
/* INPUT PARAMETERS = none */
/* */
/* RETURN CODE = 0 Successful */
/* 1 Failure */
/* */
/*****************************************************************************/
int audplay(void) /* Begin Function */
{
/*****************************************************************************/
/* LOCAL VARIABLE DEFINITIONS */
/*****************************************************************************/
unsigned char mode_s[4]; /* Temp read buffer */
unsigned char form_s[4]; /* Temp read buffer */
unsigned long cksize; /* RIFF chunk size - dword */
unsigned long bytes_read; /* bytes read in READ function */
struct waveformat_s {
unsigned int formattag; /* format category */
unsigned int nchannels; /* number of channels */
unsigned long nsamplespersec; /* sampling rate */
unsigned long navgbytespersec; /* for buffering */
unsigned int nblockalign; /* block alignment */
unsigned int nbitspersample; /* sample size */
};
struct waveformat_s waveformat;
struct audio_hpi hpi;
#if IS_DOS
unsigned long data;
#endif
wasur = 0;
/* Continue, device driver was installed ok... */
for (sy=0; sy<num_xbuffers_p; sy++) {
/* Setup our own buffer */
if ((xbuffer = (char far *)_fmalloc((size_t)xbuffer_len_p[sy]))==NULL) {
outemsg(ERROR,MALLOCERR); /* Write failed return code */
close(audhndl);
close(inhndl);
freebuffs(sy,0);
return(1);
}
if (update_flag) {
update_size += xbuffer_len_p[sy];
update_array[sy].Virt = xbuffer;
update_array[sy].length = xbuffer_len_p[sy];
xbuf->buf[sy].Virt = NULL;
xbuf->buf[sy].length = 0;
} else {
xbuf->buf[sy].Virt = xbuffer;
xbuf->buf[sy].length = xbuffer_len_p[sy];
} /* endif */
} /* endfor */
if (update_flag) {
update_ptr = update_array[0].Virt;
xbuf->size = 0;
update_index = 0;
prv_segnum = 0;
} else {
xbuf->size = xlength;
} /* endif */
xbuf->num_buffers = num_xbuffers_p;
xbuf->head = xbuf->buf[0].Virt;
xbuf->tail = xbuf->buf[0].Virt;
xbuf->count = 0;
xbuf->position = 0;
xbuf->delay = 0;
xbuf->runflags = cb_flag;
old_tail = xbuf->tail;
/* Setup our own buffer */
if ((rbuffer = (char far *)_fmalloc((size_t)RBUFFERSIZEP))==NULL) {
outemsg(ERROR,MALLOCERR); /* Write failed return code */
close(audhndl);
close(inhndl);
freebuffs(xbuf->num_buffers,rbuf->num_buffers);
return(1);
}
rbuf->size = RBUFFERSIZEP;
rbuf->num_buffers = 1;
rbuf->buf[0].Virt = rbuffer;
rbuf->buf[0].length = RBUFFERSIZEP;
rbuf->head = rbuffer;
rbuf->tail = rbuffer;
rbuf->count = 0;
rbuf->position = 0;
rbuf->delay = 0;
rbuf->runflags = 0;
if (cb_flag) {
interrupt_count = 0;
#if IS_OS2
hpi.cb = callback;
#else
hpi.cb = &callback;
data = &interrupt_count;
#if VER20
hpi.cb_ds_val = (unsigned int)(data >> 16);
#endif
#endif
} else {
hpi.cb = NULL;
} /* endif */
hpi.newxbuf = xbuf;
hpi.newrbuf = rbuf;
hpi.flags = 0;
#if IS_DOS
if(rc = ioctl(&hpi,AUDIO_HPI,audhndl)){
#else
if(rc = DosDevIOCtl(&hpi, NULL, 0x40+AUDIO_HPI, 0x80, audhndl)) {
#endif
outmsg(ERROR,HPIIOCTL); /* Write failed return code */
_settextposition(11,30);
printf("%i",rc);
endemsg(ERROR);
close(audhndl);
close(inhndl);
freebuffs(xbuf->num_buffers,rbuf->num_buffers);
return(1);
}
#if IS_DOS
direct_call = hpi.ep;
#endif
/* Determine if MIDI standard file, RIFF-MIDI file, RIFF-WAVE(PCM), or */
/* RIFF-ibmw(MU_LAW,A_LAW,ADPCM) */
read(inhndl,mode_s,4); /* read chunk type */
if ( !(strncmp(mode_s,"MThd",4) ) ) { /* MIDI header chunk? */
lseek(inhndl,0,SEEK_SET); /* Go back to top of file */
cksize = filelength(inhndl); /* entire file is 'chunk' */
file_type = 0;
/* Set up for INIT IOCtl */
init.mode = MIDI;
chan_i = NONE;
init.srate = mode_table[0].srate_low;
init.flags = mode_table[0].flags;
init.bits_per_sample = mode_table[0].bps_low;
init.bsize = mode_table[0].bsize;
init.channels = channels;
rc = play_data(cksize,init);
} else if (!(strncmp(mode_s,"RIFF",4))) { /* RIFF header chunk? */
read(inhndl,(char *)&cksize,4); /* read RIFF chunk size */
bytes_read = read(inhndl,form_s,4); /* read formtype (WAVE) */
if ((!(strncmp(form_s,"WAVE",4))) || /* WAVEform? */
(!(strncmp(form_s,"ibmw",4)))) { /* ibmwform? */
while (bytes_read == 4) { /* end of file? */
bytes_read = read(inhndl,mode_s,4);/* read fmt header id */
if ( !(strncmp(mode_s,"fmt ",4) ) ) { /* fmt chunk? */
read(inhndl,(char *)&cksize,4); /* read fmt chunk size */
read(inhndl,(char *)&waveformat,16);/* read wave format chunk */
if ( ( ((waveformat.formattag == 1) || /* Supported data? */
((waveformat.formattag >= 0x0101) &&
(waveformat.formattag <= 0x0103))) &&
(!(strncmp(form_s,"WAVE",4)))) ||
((waveformat.formattag >= 2) &&
(waveformat.formattag <= 5) &&
(!(strncmp(form_s,"ibmw",4))))) {
bytes_read = read(inhndl,mode_s,4);/* read chunk name */
while (bytes_read == 4) { /* end of file ? */
read(inhndl,(char *)&cksize,4); /* read chunk size */
if (!(strncmp(mode_s,"data",4))) { /* data chunk? */
/* Set up for INIT IOCtl */
if (waveformat.formattag == 1) {
init.mode = PCM;
file_type = 5;
} else if ((waveformat.formattag == 2) ||
(waveformat.formattag == 0x0101)) {
init.mode = MU_LAW;
file_type = 16;
} else if ((waveformat.formattag == 3) ||
(waveformat.formattag == 0x0102)) {
init.mode = A_LAW;
file_type = 20;
} else if ((waveformat.formattag == 4) ||
(waveformat.formattag == 0x0103)) {
init.mode = ADPCM;
file_type = -4; /* have 5 less than where it really */
/* starts so that when the rate is */
/* done - it ends up correctly */
} else { /* must == 5 */
init.mode = CVSD;
file_type = 25;
} /* endif */
init.srate = waveformat.nsamplespersec;
if (init.srate == 11025) {
file_type += 1;
} else if (init.srate == 22050) {
file_type += 2;
} else if (init.srate == 44100) {
if (mode == ADPCM) {
file_type += 4;
} else {
file_type += 3;
} /* endif */
} else if (init.srate == 7875) {
file_type += 26;
} else if (init.srate == 31500) {
file_type += 27;
} else if (init.srate == 48000) {
file_type += 28;
} /* endif */
init.bits_per_sample = waveformat.nbitspersample;
if (init.bits_per_sample == 8) {
init.flags = FIXED;
} else { /* assume 16 bits per sample */
init.flags = FIXED+TWOS_COMPLEMENT;
if (init.srate == 7875 || init.srate == 31500 ||
init.srate == 48000) {
file_type += 3;
} else {
file_type += 4;
} /* endif */
} /* endif */
init.bsize = BSIZE_R;
init.channels = waveformat.nchannels;
if (init.channels == 1) {
if (mode != ADPCM) {
chan_i = MONO;
} else {
chan_i = NONE;
} /* endif */
} else {
if (mode != ADPCM) {
chan_i = STEREO;
} else {
chan_i = NONE;
if (mode_i == AVC_MUSIC)
file_type++; /* Make it AVC_STEREO if 2 channels */
} /* endif */
} /* endif */
rc = play_data(cksize,init);
} else { /* not data chunk */
/* ignore this chunk */
lseek(inhndl,cksize,SEEK_CUR);
} /* endif */
/* read next chunk */
bytes_read = read(inhndl,mode_s,4);/* read chunk name*/
} /* end while not end of file */
} else { /* not supported data */
outemsg(ERROR,NOTPCMDATA);
close(audhndl);
close(inhndl);
freebuffs(xbuf->num_buffers,rbuf->num_buffers);
return(1);
} /* endif waveformat.formattag == 1,2,3, or 4 */
} else { /* unexpected chunk - ignore it */
/* ignore this chunk */
lseek(inhndl,cksize,SEEK_CUR);
outemsg(WARNING,UNCHUNK);
} /* endif mode_s == 'fmt' */
bytes_read = (long)read(inhndl,mode_s,4); /* read chunk name */
} /* end while not end of file */
} else if ( !(strncmp(form_s,"RMID",4) ) ) { /* MIDI inside RIFF? */
bytes_read = read(inhndl,mode_s,4);/* read chunk name 'data' */
while (bytes_read == 4) { /* end of file ? */
read(inhndl,(char *)&cksize,4); /* read chunk size */
if (!(strncmp(mode_s,"data",4))) { /* data chunk? */
/* Set up for INIT IOCtl */
init.mode = MIDI;
init.srate = mode_table[0].srate_low;
init.flags = mode_table[0].flags;
init.bits_per_sample = mode_table[0].bps_low;
init.bsize = mode_table[0].bsize;
init.channels = channels;
chan_i = NONE;
rc = play_data(cksize,init);
} else { /* not data chunk */
/* ignore this chunk */
lseek(inhndl,cksize,SEEK_CUR);
outemsg(WARNING,UNCHUNK);
} /* endif */
/* read next chunk */
bytes_read = read(inhndl,mode_s,4); /* read chunk name */
} /* end while not end of file */
} else { /* unsupported RIFF file */
outemsg(ERROR,UNSUPRIFF);
close(audhndl);
close(inhndl);
freebuffs(xbuf->num_buffers,rbuf->num_buffers);
return(1);
} /* endif form_s == WAVE */
} else { /* unrecognized file */
outemsg(ERROR,UNRECOG);
close(audhndl);
close(inhndl);
freebuffs(xbuf->num_buffers,rbuf->num_buffers);
return(1);
} /* endif mode_s == MThd */
outmsg(VBHELP,CLEARSCRN);
return(0);
} /* end AUDPLAY */
/*****************************************************************************/
/* */
/* FUNCTION NAME = play_data */
/* */
/* FUNCTION = Sets up the audio device driver to play the recognized */
/* input file. */
/* */
/* INPUT PARAMETERS = cksize - size of chunk to be played */
/* init - initialization structure */
/* */
/* RETURN CODE = 0 Successful */
/* 1 Escape from program */
/* */
/*****************************************************************************/
int play_data (unsigned long cksize, struct audio_init init)
{
/*****************************************************************************/
/* LOCAL VARIABLE DEFINITIONS */
/*****************************************************************************/
#if IS_DOS
union REGS dosregs;
#endif
struct audio_control control;
struct audio_change change;
int key_hit;
char ch;
/* Issue INIT IOCTL call */
init.operation = PLAY;
init.rc = 0;
init.reserved = NULL;
init.version_level = CURRENT_VERSION;
#if IS_DOS
if(direct_call == NULL){
rc = ioctl(&init,AUDIO_INIT,audhndl);
}else{
rc = (*direct_call)(EP_INIT,(char far *)&init,23);
}
if (rc) {
#else
if(rc = DosDevIOCtl(&init, NULL, 0x40+AUDIO_INIT, 0x80, audhndl)) {
#endif
outmsg(ERROR,EINITIOCTL);
_settextposition(11,30);
printf("%i",rc);
endemsg(ERROR);
close(audhndl);
close(inhndl);
return(1);
}
if(init.rc != 0){
outmsg(ERROR,INITFAILED); /* Write failed return code */
_settextposition(11,30);
printf("%i",init.rc);
endemsg(ERROR);
close(audhndl);
close(inhndl);
return(1);
}
if (init.flags & BESTFIT_PROVIDED) {
mode = init.mode;
channels = init.channels;
outemsg(WARNING,BESTFIT); /* Warn user given configuration */
/* was not supported and a best */
/* fit configuration was done */
} /* endif best fit was provided */
if (init.flags & LOAD_CODE) { /* Load DSP code module */
if (rc = dspload(&init.loadpath[0], audhndl)) {
outmsg(ERROR,EDSPLOAD); /* Write failed return code */
_settextposition(11,30);
printf("%i",rc);
endemsg(ERROR);
close(audhndl);
close(inhndl);
return(1);
}
}
/* Issue CHANGE IOCtl */
control.position = 0; /* Do it now */
control.ioctl_request = AUDIO_CHANGE; /* Change configuration */
control.return_code = 0; /* zero out return code field */
control.request_info = &change; /* Request data = change struct */
change.input_list[0].devtype = 0;
change.input_list[0].devnum = DEVICE_1;
change.output_list[0].devtype = source_output;
change.output_list[0].devnum = DEVICE_1;
change.input_list[1].devtype = NULL_INPUT;
change.input_list[1].devnum = DEVICE_1;
change.output_list[1].devtype = NULL_OUTPUT;
change.output_list[1].devnum = DEVICE_1;
change.input = INPUTS_LISTED;
change.output = OUTPUTS_LISTED; /* Output select */
change.monitor = monitor; /* Monitor not applicable */
cur_volume = 0x7fffffff;
change.volume = cur_volume; /* Volume set to maximum */
change.volume_delay = delay; /* Set volume now */
change.balance = cur_balance; /* Balance set to mid-point */
change.balance_delay = delay; /* Set balance now */
change.treble = 0x3fffffff; /* Mid point */
change.bass = 0x3fffffff; /* Mid point */
change.pitch = 0; /* */
if (mastervol) {
change.dev_info = &devinfo; /* Device dependent data */
} else {
change.dev_info = NULL; /* No device dependent data */
}
change.input_gain = 0; /* No input gain */
change.mode_info = NULL; /* No mode dependent data */
#if IS_DOS
if(direct_call == NULL){
rc = ioctl(&control,AUDIO_CONTROL,audhndl);
}else{
rc = (*direct_call)(EP_CONTROL,(char far *)&control,23);
}
/*************************************************************************/
/* Issue IOCTL set device parameters to force BINARY mode */
/* (otherwise an 0x1a read will cause DOS to assume EOF) */
/* You might need to uncomment this if you want to build */
/* a DOS only version. */
/*************************************************************************/
dosregs.x.ax=0x4401;
dosregs.x.bx=audhndl;
dosregs.x.dx=0x00a0;
intdos(&dosregs,&dosregs);
/*************************************************************************/
if (rc) {
#else
if(rc = DosDevIOCtl(&control, NULL, 0x40+AUDIO_CONTROL, 0x80, audhndl)) {
#endif
outmsg(ERROR,ECHNGIOCTL);
_settextposition(11,30);
printf("%i",rc);
endemsg(ERROR);
close(audhndl);
close(inhndl);
return(1);
}
if (init.mode == MIDI) {
/* Enable timing data, and 48ppqn. */
/* Disable input clocks */
dcwrite(timinit,10,num_xbuffers_p);
} /* endif */
outmsg(USERINPUT,CLEARSCRN);
outmsg(HELP,BLANK);
outmsg(HELP,PLAYING1);
_settextposition(9,((short)(strlen(help_msg[PLAYING1][0]))+5));
printf("%s - %s %s",iname,file_type_msg[file_type],mono_stereo_msg[chan_i]);
_settextposition(10,((short)(strlen(help_msg[PLAYING1][1]))+5));
printf("%s",audioname);
if (pos_flag) {
_settextposition(11,5);
_setbkcolor(AQUA); /* Set background color */
_settextcolor(BLACK); /* Set foreground/text color */
_outtext(extra_msg[POSITION]);
} /* endif */
if (cb_flag) {
_settextposition(17,5);
_setbkcolor(AQUA); /* Set background color */
_settextcolor(BLACK); /* Set foreground/text color */
_outtext(extra_msg[CBCOUNT]);
} /* endif */
_settextposition(13,((short)(strlen(help_msg[PLAYING1][4]))+5));
printf("%s",cur_volume_s);
_settextposition(14,((short)(strlen(help_msg[PLAYING1][5]))+5));
printf("%s",cur_balance_s);
outmsg(STATUS,STARTSTOP);
outmsg(VBHELP,VOLBAL);
started = 0;
if (init.mode == MIDI) {
/* Start getting data from MIDI file and playing it */
rc=midi2seq(cksize);
} else {
/* Start getting data from RIFF-PCM file and playing it */
rc=send_data(mode_s,cksize,inhndl); /* note mode_s dummy var */
#if IS_OS2
rc = DosSetPrty(0,1,0,PidInfo.pid);
#endif
if (audiowait) {
while (!(xbuf->runflags & STARTED))
key_hit=send_data(&ch,0,0); /* Waste time waiting to start */
#if IS_DOS
if(rc = ioctl(0,AUDIO_WAIT,audhndl)){
#else
if(rc = DosDevIOCtl(0, NULL, 0x40+AUDIO_WAIT, 0x80, audhndl)) {
#endif
outmsg(ERROR,WAITIOCTL); /* Write failed return code */
_settextposition(11,30);
printf("%i",rc);
endemsg(ERROR);
close(audhndl);
close(inhndl);
freebuffs(xbuf->num_buffers,rbuf->num_buffers);
return(1);
}
update_count();
/* loop until get ESC character */
while(!user_esc) {
if (kbhit()) {
key_hit = getch();
if (key_hit == ESC) user_esc = TRUE;
}
}
} else {
while (!user_esc) {
key_hit=send_data(&ch,0,0); /* Waste time for music to finish*/
/* or for user to press ESCape */
update_count();
if ((xbuf->count <= blocksize*2)) {
strcpy(status,"Finished");
_settextposition(12,((short)(strlen(help_msg[PLAYING1][3]))+5));
printf("%s",status);
if (old_runtotal != runtotal) {
old_runtotal = runtotal;
_settextposition(16,((short)(strlen(help_msg[PLAYING1][7]))+5));
printf("%6.6ld",runtotal);
} /* endif */
if (batch) user_esc = TRUE;
if (!batch) {
/* loop until get ESC character */
while(!user_esc) {
if (kbhit()) {
key_hit = getch();
if (key_hit == ESC) user_esc = TRUE;
}
if (!supress) {
if (old_playtotal != playtotal) {
_settextposition(15,((short)(strlen(help_msg[PLAYING1][6]))+5));
printf("%6.6ld",playtotal);
old_playtotal = playtotal;
} /* endif */
if (pos_flag) {
_settextposition(11,((short)(strlen(extra_msg[POSITION]))+5));
printf("%6.6ld",xbuf->position);
} /* endif */
if (cb_flag) {
_settextposition(17,((short)(strlen(extra_msg[CBCOUNT]))+5));
printf("%6.6ld",interrupt_count);
} /* endif */
} /* endif */
}
} /* endif */
} /* endif */
} /* end_while */
} /* endif */
#if IS_OS2
rc = DosSetPrty(2,1,priority,PidInfo.pid);
#endif
} /* endif */ /* for call */
outmsg(HELP,CLEARSCRN);
return(rc);
} /* end PLAY_DATA */
/*****************************************************************************/
/* */
/* FUNCTION NAME = senddata */
/* */
/* FUNCTION = Writes data from converted MIDI file to the audio device */
/* and checks for any input from the user via keyboard. */
/* */
/* INPUT PARAMETERS = data - buffer with data to be written */
/* count - number of bytes to be written from data */
/* instring - file handle (used for RIFF files) */
/* */
/* RETURN CODE = 0 Successful */
/* 1 Escape from program */
/* */
/*****************************************************************************/
int send_data (unsigned char *data, unsigned long count, int instring)
{
/*****************************************************************************/
/* LOCAL VARIABLE DEFINITIONS */
/*****************************************************************************/
unsigned char *tdata; /* temp ptr to data */
int ch=0;
unsigned long write_num;
char wrap_it;
struct audio_update update;
unsigned char last_one;
unsigned int num_returned;
tdata = data;
do {
if (update_flag) {
/* See how much room is available in the update_array */
write_num = update_size - update_cnt;
if(write_num > 0x7fff) write_num = 0x7fff; /* Limit to int range */
/* Don't allow fread to wrap around the buffer */
if(write_num >= (unsigned long)(update_array[update_segnum].Virt-update_ptr
+update_array[update_segnum].length)){
write_num = (unsigned long)(update_array[update_segnum].Virt-update_ptr
+update_array[update_segnum].length);
wrap_it = TRUE;
} else {
wrap_it = FALSE;
}
/* make sure room in buffer for everything to be written */
if (write_num >= count) {
write_num = count;
last_one = 1;
} else {
last_one = 0;
} /* endif */
if (write_num > 0) {
if (init.mode == MIDI) {
outmsg(ERROR,EUPDATEMIDI);
close(audhndl);
close(inhndl);
freebuffs(xbuf->num_buffers,rbuf->num_buffers);
return(1);
} else { /* RIFF-PCM */
/* Fill up the buffer directly from the RIFF file */
read(instring,(char *)update_ptr,(unsigned int)write_num);
available_buffs++;
} /* endif */
/* Adjust length of buffer for the last buffer sent down in */
/* case it wasn't filled completely */
if (last_one) {
update_array[update_segnum].length = write_num;
} /* endif */
tdata += write_num; /* reposition just in case entire msg didn't fit */
if (wrap_it) {
if (++update_segnum >= num_xbuffers_p) {
update_segnum = 0;
} /* endif */
update_ptr = update_array[update_segnum].Virt;
} else {
update_ptr += write_num;
} /* endif */
update_cnt += write_num;
} else {
write_num = 0;
} /* endif write_num > 0 */
count -= write_num; /* update number of bytes left to write */
while ((available_buffs) || (xbuf->tail_segnum != prv_segnum)) {
/* Set up for UPDATE IOCtl */
update.iobuf_type = 0; /* XMIT buffer type */
if (available_buffs) {
update.buffer_address = update_array[update_index].Virt;
update.buffer_length = update_array[update_index].length;
if (++update_index >= num_xbuffers_p)
update_index = 0;
available_buffs--;
} else {
update.buffer_address = NULL;
update.buffer_length = 0;
} /* endif */
if (xbuf->tail_segnum == prv_segnum) {
num_returned = 0;
} else {
if (prv_segnum < xbuf->tail_segnum) {
num_returned = xbuf->tail_segnum - prv_segnum;
} else {
num_returned = num_xbuffers_p - prv_segnum + xbuf->tail_segnum;
} /* endif */
/* tail segnum always equals zero after AUDIO_UPDATE for xmit */
prv_segnum = 0;
} /* endif */
#if IS_DOS
if(direct_call == NULL){
rc = ioctl(&update,AUDIO_UPDATE,audhndl);
}else{
rc = (*direct_call)(EP_UPDATE,(char far *)&update,23);
}
if (rc) {
#else
if(rc = DosDevIOCtl(&update, NULL, 0x40+AUDIO_UPDATE, 0x80, audhndl)) {
#endif
outmsg(ERROR,EUPDATEIOCTL);
_settextposition(11,30);
printf("%i",rc);
endemsg(ERROR);
close(audhndl);
close(inhndl);
freebuffs(xbuf->num_buffers,rbuf->num_buffers);
return(1);
}
while (num_returned) {
update_cnt -= update_array[rtn_segnum].length;
if (++rtn_segnum >= num_xbuffers_p)
rtn_segnum = 0;
num_returned--;
} /* endwhile */
runtotal += update.buffer_length;
} /* endwhile */
// update_count(); Not valid calculation when AUDIO_UPDATE is used
} else { /* not using AUDIO_UPDATE */
/* See how much room is available in the MIDI queue */
write_num = xbuf->size - xbuf->count;
if(write_num > 0x7fff) write_num = 0x7fff; /* Limit to int range */
/* make sure room in buffer for everything to be written */
if (write_num >= count) write_num = count;
/* Don't allow fread to wrap around the buffer */
if(write_num >= (unsigned long)(xbuf->buf[xbuf->head_segnum].Virt-xbuf->head
+xbuf->buf[xbuf->head_segnum].length)){
write_num = (unsigned long)(xbuf->buf[xbuf->head_segnum].Virt-xbuf->head
+xbuf->buf[xbuf->head_segnum].length);
wrap_it = TRUE;
} else {
wrap_it = FALSE;
}
if (write_num > 0) {
if (init.mode == MIDI) {
/* Fill up the buffer by putting converted data from 'data' into */
/* 'xbuf' */
memcpy((unsigned char *)xbuf->head,tdata,(int)write_num);
} else { /* RIFF-PCM */
/* Fill up the buffer directly from the RIFF file */
read(instring,(char *)xbuf->head,(unsigned int)write_num);
} /* endif */
tdata += write_num; /* reposition just in case entire msg didn't fit */
if (wrap_it) {
if (++xbuf->head_segnum >= num_xbuffers_p) {
xbuf->head_segnum = 0;
} /* endif */
xbuf->head = xbuf->buf[xbuf->head_segnum].Virt;
} else {
xbuf->head += write_num;
} /* endif */
xbuf->runflags |= IOBUF_LOCK;
xbuf->count += write_num;
xbuf->runflags &= ~IOBUF_LOCK;
runtotal += write_num;
} else {
write_num = 0;
} /* endif write_num > 0 */
update_count();
count -= write_num; /* update number of bytes left to write */
} /* endif */
/* Any input data? */
if(rbuf->count){
outmsg(WARNING,BLANK);
outmsg(WARNING,DISCARD);
_settextposition(19,((short)(strlen(warning_msg[DISCARD][1]))+5));
printf("%i",rbuf->count);
rbuf->tail = rbuf->head;
rbuf->runflags |= IOBUF_LOCK;
rbuf->count = 0;
rbuf->runflags &= ~IOBUF_LOCK;
}
if (batch && !started) {
started = 1;
xbuf->runflags |= STARTED;
strcpy(status,"Running ");
} /* endif */
/**************************/
/* Process keyboard input */
/**************************/
if (kbhit()) {
ch=getch();
switch(ch) {
case ' ':
if (!started) { /* if not started, issue START */
started = 1;
xbuf->runflags |= STARTED;
strcpy(status,"Running ");
} else if (started==1) { /* if running, issue PAUSE */
started=2;
xbuf->runflags |= PAUSED;
strcpy(status,"Paused ");
} else { /* if paused, issue RESUME */
started = 1;
xbuf->runflags &= ~PAUSED;
strcpy(status,"Resumed ");
}
break;
case 'r': /* Balance Right */
case 'R':
cur_balance = 0x7fffffff;
strcpy(cur_balance_s,"Right ");
change_settings();
break;
case 'L': /* Balance Left */
case 'l':
cur_balance = 0;
strcpy(cur_balance_s,"Left ");
change_settings();
break;
case 'm': /* Balance Middle */
case 'M':
cur_balance = 0x3fffffff;
strcpy(cur_balance_s,"Middle");
change_settings();
break;
case '0': /* Volume Settings (0 - 9) */
strcpy(cur_volume_s,"*---------");
cur_volume = (0x7fffffff/9) * (ch-'0');
change_settings();
break;
case '1':
strcpy(cur_volume_s,"-*--------");
cur_volume = (0x7fffffff/9) * (ch-'0');
change_settings();
break;
case '2':
strcpy(cur_volume_s,"--*-------");
cur_volume = (0x7fffffff/9) * (ch-'0');
change_settings();
break;
case '3':
strcpy(cur_volume_s,"---*------");
cur_volume = (0x7fffffff/9) * (ch-'0');
change_settings();
break;
case '4':
strcpy(cur_volume_s,"----*-----");
cur_volume = (0x7fffffff/9) * (ch-'0');
change_settings();
break;
case '5':
strcpy(cur_volume_s,"-----*----");
cur_volume = (0x7fffffff/9) * (ch-'0');
change_settings();
break;
case '6':
strcpy(cur_volume_s,"------*---");
cur_volume = (0x7fffffff/9) * (ch-'0');
change_settings();
break;
case '7':
strcpy(cur_volume_s,"-------*--");
cur_volume = (0x7fffffff/9) * (ch-'0');
change_settings();
break;
case '8':
strcpy(cur_volume_s,"--------*-");
cur_volume = (0x7fffffff/9) * (ch-'0');
change_settings();
break;
case '9':
strcpy(cur_volume_s,"---------*");
cur_volume = (0x7fffffff/9) * (ch-'0');
change_settings();
break;
case ESC: /* Esc = quit */
xbuf->runflags &= ~STARTED;
strcpy(status,"Stopped ");
xbuf->count = 0;
xbuf->head_segnum = 0;
xbuf->tail_segnum = 0;
xbuf->head = xbuf->tail = xbuf->buf[0].Virt;
started = 1;
user_esc = TRUE;
break;
default:
break;
} /* end switch (ch) */
_settextposition(12,((short)(strlen(help_msg[PLAYING1][3]))+5));
printf("%s",status);
} /* endif keyboard hit */
if (xbuf->runflags & IOB_UNDERRUN) {
wasur = 1;
outmsg(WARNING,UNDERRUN);
xbuf->runflags &= ~IOB_UNDERRUN;
} else if (wasur) {
wasur = 0;
outmsg(WARNING,CLEARSCRN);
} /* endif */
#if IS_OS2
if (cb_flag && (xbuf->count == xbuf->size) && (count)) {
/* wait for semaphore to be cleared before writing more data */
rc = DosSemSetWait(callback,50);
if (rc) {
error_count++;
} else {
interrupt_count++;
} /* endif */
} /* endif */
#endif
if (!supress) {
if (old_runtotal != runtotal) {
old_runtotal = runtotal;
_settextposition(16,((short)(strlen(help_msg[PLAYING1][7]))+5));
printf("%6.6ld",runtotal);
} /* endif */
if (pos_flag) {
_settextposition(11,((short)(strlen(extra_msg[POSITION]))+5));
printf("%6.6ld",xbuf->position);
} /* endif */
if (cb_flag) {
_settextposition(17,((short)(strlen(extra_msg[CBCOUNT]))+5));
printf("%6.6ld",interrupt_count);
} /* endif */
} /* endif */
} while ((count > 0) && /* Keep looping until all data was written */
(!(user_esc))); /* or the user wants to end the program */
return(ch);
} /* end send_data */
/*****************************************************************************/
/* */
/* FUNCTION NAME = update_count */
/* */
/* FUNCTION = Will calculate amount of data acutally played and output */
/* it to the screen. */
/* */
/* INPUT PARAMETERS = */
/* */
/* RETURN CODE = 0 Successful */
/* 1 Failure */
/* */
/*****************************************************************************/
void update_count(void) /* Begin Function */
{
int found;
if (!update_flag) {
new_tail = xbuf->tail;
new_segnum = xbuf->tail_segnum;
found = FALSE;
x = 0;
if (old_segnum != new_segnum) {
playtotal += xbuf->buf[old_segnum].Virt + xbuf->buf[old_segnum].length
- old_tail;
if (++old_segnum >= num_xbuffers_p) {
old_segnum = 0;
} /* endif */
while (old_segnum != new_segnum) {
playtotal += xbuf->buf[old_segnum].length;
if (++old_segnum >= num_xbuffers_p) {
old_segnum = 0;
} /* endif */
} /* endwhile */
old_tail = xbuf->buf[old_segnum].Virt;
} /* endif */
if (old_tail < new_tail) {
playtotal += new_tail - old_tail;
} else if (old_tail > new_tail) {
playtotal += xbuf->buf[old_segnum].length - (old_tail - new_tail);
} /* endif */
old_tail = new_tail;
if (old_playtotal != playtotal) {
old_playtotal = playtotal;
if (!supress) {
_settextposition(15,((short)(strlen(help_msg[PLAYING1][6]))+5));
printf("%6.6ld",playtotal);
if (pos_flag) {
_settextposition(11,((short)(strlen(extra_msg[POSITION]))+5));
printf("%6.6ld",xbuf->position);
} /* endif */
} /* endif */
} /* endif */
} /* endif */
} /* update_count */
/*****************************************************************************/
/* */
/* FUNCTION NAME = midi2seq */
/* */
/* FUNCTION = Convert MIDI standard file to .SEQ format file */
/* */
/* INPUT PARAMETERS = byte_count - length of chunk */
/* */
/* RETURN CODE = 0 Successful */
/* 1 Failure */
/* */
/*****************************************************************************/
int midi2seq(unsigned long byte_count) /* Begin Function */
{
/*****************************************************************************/
/* LOCAL VARIABLE DEFINITIONS */
/*****************************************************************************/
char keynums[16][16]; /* id of notes currently on */
char maxnotes[16]; /* max # notes for each chan */
char numnotes[16]; /* # notes current on */
char totnumnotes; /* total # of notes on */
char totmaxnotes; /* total max # of notes ever on */
FILE *tmpstr = NULL; /* Temp file during merge */
int chan; /* Temporary MIDI channel var */
int cpqn; /* Clocks per quarter note */
int division; /* Division from header */
int smpte; /* SMPTE timing flag */
int sysex; /* SysEx flag */
int tempo; /* Current Tempo in bpm */
unsigned int trk; /* Temp current trk num */
int x; /* Temporary variable */
int key_hit;
unsigned int maxtrack; /* Current track number */
unsigned char b3; /* temp MIDI byte 3 */
unsigned char ch; /* temp MIDI byte read from inhndl */
unsigned char tptr; /* temp char pointer */
unsigned char metatype; /* Meta type id */
unsigned char mrunstat; /* Master running status */
unsigned char tsden; /* Time signature denominator */
unsigned char tsmet; /* # clocks between met clicks */
unsigned char tsnum; /* Time signature numerator */
unsigned char ts32pq; /* # 1/32 notes per MIDI clock */
unsigned char tbuf[4097]; /* Temp read buffer */
unsigned long len; /* Chunk length */
unsigned long len2; /* Event len */
unsigned long tlong; /* temp long var (for tempo) */
unsigned int format; /* Format type from header */
unsigned int ntracks; /* # tracks from header */
unsigned int progchgs[16]; /* # prog changes each channel */
unsigned long trksize[128]; /* Track size */
unsigned char *trkbuffer[128]; /* ptr to start of buffer */
unsigned char runstat[128]; /* Current running status */
/*****************************************************************************/
/**************************************************************************/
/* Initialize, and Set default values */
/**************************************************************************/
midi_buff_index = 0;
totnumnotes = 0;
totmaxnotes = 0;
/* Initialize the number of notes, max number of notes, and number of */
/* program changes to 0 for all channels. */
for ( chan=0; chan<16; chan++) {
numnotes[chan] = 0;
maxnotes[chan] = 0;
progchgs[chan] = 0;
/* initialize all notes to 'not on' */
for (x=0; x<16; x++) {
keynums[chan][x] = -1;
} /* end for x=0 to 16 */
} /* end for chan=0 to 16 */
tempo = 120; /* 000 Provide default tempo */
smpte = 0; /* 000 clear SMPTE flag */
cpqn = 96; /* 000 Provide default CPQN */
sysex = 0; /* 000 Clear SysEx flag */
maxtrack = 0; /* 000 count of tracks proc'd */
/**************************************************************************/
/* Read each CHUNK, and process based on type */
/* This while loop will read each chunk and save the track chunks in */
/* trkdata() */
/**************************************************************************/
key_hit = 0;
while ((user_esc == FALSE) /* 000 Loop until key pressed */
&& (byte_count > 0) /* 000 not at end of chunk */
&& (read(inhndl,tbuf,8) == 8) ) { /* 000 chunk type & len */
byte_count -= 8; /* Decrement count */
/* Determine length of chunk */
len = (tbuf[4]<<24) /* 000 high byte 1st */
+(tbuf[5]<<16) /* 000 2nd */
+(tbuf[6]<<8) /* 000 3rd */
+(tbuf[7]); /* 000 low byte last (4th) */
/***********************************************************************/
/* HEADER CHUNK */
/***********************************************************************/
if ( !(strncmp(tbuf,"MThd",4) ) ) { /* 000 HEADER CHUNK */
if (len > 4095) { /* 000 Is our buffer big enough? */
outemsg(ERROR,HDRTOOBIG); /* No, error message */
exit(8); /* 000 and exit */
} else { /* buffer OK */
/* Read entire header chunk into tbuf */
if ( (unsigned long)read(inhndl,tbuf,(int)len) !=len ) {
outemsg(ERROR,ERRHDRDATA); /* error message */
exit(8); /* 000 and exit */
} /* endif */
byte_count -= len; /* Decrement counter */
/* Determine format type: 0, 1, or 2 */
format = (tbuf[0]<<8) /* 000 Format type MSB */
+tbuf[1]; /* 000 and LSB */
/* Determine # of tracks in file - */
/* format 0 = 1 track always */
ntracks = (tbuf[2]<<8) /* 000 # tracks MSB */
+tbuf[3]; /* 000 and LSB */
/* Determine the meaning of delta times */
division = (tbuf[4]<<8) /* 000 Division MSB */
+tbuf[5]; /* 000 and LSB */
if (division < 0) { /* if bit 15 = 1, then SMPTE time */
/* Calculate number of counts per */
/* quarter note */
smpte = 1; /* 000 set SMPTE flag */
cpqn = -(division>>8); /* 000 # frames/sec */
cpqn *= division & 0xff; /* 000 * ticks/frame */
} else { /* metrical time */
cpqn = division; /* 000 */
} /* endif SMPTE time */
/* Write timing control SysEx */
timinit[7] = (unsigned char)((cpqn / 24)-1);
key_hit=send_data(midi_buff,midi_buff_index,0); /* Send anything in buff */
midi_buff_index = 0;
key_hit=send_data(timinit,10,0); /* Send data to the audio device */
} /* endif len > 4095 */
/***********************************************************************/
/* TRACK CHUNK */
/***********************************************************************/
} else if ( !(strncmp(tbuf,"MTrk",4) ) ) { /* 000 track chunk */
/* Set up buffer for this tracks data */
if ( !(trkbuffer[maxtrack]=(unsigned char *)malloc(( (int)len+1) )) ) {
outemsg(ERROR,NOMEMORY); /* Display error message */
exit(12); /* 000 and exit rc=12 */
} /* endif invalid trkbuffer allocation */
/* Set data -> to start */
trkdata[maxtrack] = trkbuffer[maxtrack];
trksize[maxtrack] = len; /* 000 Save length of track */
trklen[maxtrack] = len; /* 000 remaining length */
/* Read track data into track's buffer */
if (read(inhndl,trkbuffer[maxtrack],(int)len) != (int)len) {
outemsg(ERROR,ERRTRKDATA); /* Display error message */
exit(16); /* 000 and exit rc=16 */
} /* endif can't read track data */
byte_count -= len; /* Decrement counter */
maxtrack++;
} else { /* unknown chunk */
outmsg(WARNING,UNCHUNK);
lseek(inhndl,len,SEEK_CUR); /* 000 skip over it */
} /* endif header chunk */
} /* end while user_esc == FALSE */
/**************************************************************************/
/* Now process each track's data which is now in trkdata[] */
/**************************************************************************/
for (trk=0; trk<maxtrack; trk++) { /* Initialize data */
runstat[trk] = 0; /* 000 Init. running status */
/* Preload delta's for all tracks */
delta[trk] = 0; /* Init. delta time */
/* get delta value - which is of */
/* variable length */
do { /* get all delta bytes */
ch = *trkdata[trk]++; /* Read next byte */
trklen[trk]--; /* Reduce remaining len */
delta[trk] = (delta[trk]<<7) /* Shift delta and */
+(ch & 0x7f); /* add next delta byte */
} while (ch & 0x80); /* Until bit 7 is clear */
} /* end for trk=0 to maxtrack */
mrunstat = 0; /* Clear master running status */
remtracks = maxtrack; /* Set # of tracks to do */
/* Do this for all tracks */
while (remtracks && (user_esc == FALSE)) { /* Continue until all gone */
len=0xffffffff; /* Some ridiculously big # */
for (trk=0; trk<maxtrack; trk++) { /* Find the smallest delta */
/* Determine which track has the smallest*/
/* delta and store in len */
if (delta[trk] < len) { /* Is it the smallest delta? */
len = delta[trk]; /* if so, save it */
} /* endif smallest delta */
} /* end for trk=0 to maxtrack len now == smallest delta */
/* Write out timing info */
len2 = len;
num_of_f8s += len2;
while (len2 > 0x3fff) { /* Need multiple SysExs? */
timesysex[5] = 0x7f; /* Yes, send max lsb */
timesysex[6] = 0x7f; /* and msb */
key_hit=send_data(midi_buff,midi_buff_index,0); /* Send anything in buff */
midi_buff_index = 0;
key_hit=send_data(timesysex,8,0); /* Write it */
mrunstat = 0; /* Clear master run stat */
len2 -= 0x3fff; /* reduce remaining count */
} /* end while len2 > 0x3ffff */
if (len2 > 8) { /* Need to use a SysEx? */
timesysex[5] = (unsigned char)(len2 & 0x7f); /* Yes, set lsb */
timesysex[6] = (unsigned char)(len2 >> 7); /* and msb */
key_hit=send_data(midi_buff,midi_buff_index,0); /* Send anything in buff */
midi_buff_index = 0;
key_hit=send_data(timesysex,8,0); /* Write it */
mrunstat = 0; /* Clear master run stat */
} else while(len2--) { /* No, just write F8's */
ch = 0xf8;
buff_data(ch);
} /* end while len2-- */
/* send out data in order of */
/* smallest delta track goes */
/* next */
if (user_esc == FALSE) {
for (trk=0; trk<maxtrack; trk++){ /* Now proc each ready trk */
if ( (delta[trk] < 0xffffffff) /* Is this trk still valid */
&& ((delta[trk]-=len)==0) /* Is it time to do it? */
&& (user_esc == FALSE)) {
/* Now read in event */
ch = nextbyte(trk); /* Go get next byte */
/**************************************************************/
/* SYSEX EVENT */
/**************************************************************/
if (ch==0xf0 || ch==0xf7) { /* SysEx Event */
runstat[trk] = 0; /* Cancel running status because of */
/* system exclusive message */
if (ch==0xf0) buff_data(ch);/*Write if F0 byte*/
/* Read in variable length event len */
len2 = 0; /* Clear event len */
do { /* get all len bytes */
ch = nextbyte(trk); /* Read next byte */
len2 = (len2<<7) /* Shift delta and */
+(ch & 0x7f); /* add next byte */
} while (ch & 0x80); /* Until bit 7 is 0 */
if (len2 < 4096){ /* Make sure there's room */
key_hit=send_data(midi_buff,midi_buff_index,0); /* Send anything in buff */
midi_buff_index = 0;
key_hit=send_data(trkdata[trk],(long)len2,0);
trkdata[trk]+=len2; /* Updata pointer */
trklen[trk] -= len2; /* and rem len */
} else { /* no room */
outemsg(ERROR,NOMEMSYS);
trkdata[trk] += len2;
trklen[trk] -= len2;
} /* endif room */
/**************************************************************/
/* META EVENT */
/**************************************************************/
} else if (ch==0xff) { /* Meta event ? */
metatype = nextbyte(trk); /* Get Meta Type */
runstat[trk] = 0; /* Cancel running status */
/* Read in variable length event len */
len2 = 0; /* Clear event len */
do { /* get all len bytes */
ch = nextbyte(trk); /* Read next byte */
len2 = (len2<<7) /* Shift delta and */
+(ch & 0x7f); /* add next byte */
} while (ch & 0x80); /* Until bit 7 is 0 */
switch(metatype){ /* Process meta events */
case 0x00: /* Sequence Number */
case 0x01: /* Text */
case 0x02: /* Copyright Notice */
case 0x03: /* Sequence/Track name */
case 0x04: /* Instrument Name */
case 0x05: /* Lyric */
case 0x06: /* Marker */
case 0x07: /* Cue Point */
case 0x20: /* MIDI Channel Prefix */
case 0x2f: /* End of Track */
break;
case 0x51: /* Tempo */
tlong = *trkdata[trk]; /* usecs per qtr note */
tlong <<= 8; /* shift left a byte */
tlong += *(trkdata[trk]+1); /* get next */
tlong <<= 8; /* shift left 1 more byte*/
tlong += *(trkdata[trk]+2); /* get lsb */
tempo = (int)(60000000/tlong);
tempo_sysex[6] = (unsigned char)((tempo*10) & 0x7f);
tempo_sysex[7] = (unsigned char)((tempo*10) >> 7);
key_hit=send_data(midi_buff,midi_buff_index,0); /* Send anything in buff */
midi_buff_index = 0;
key_hit=send_data(tempo_sysex,10,0);
break;
case 0x54: /* SMPTE Offset */
break;
case 0x58: /* Time Signature */
tsnum= *trkdata[trk]; /* numerator */
tsden= *(trkdata[trk]+1); /* denominator 2**-n */
tsmet= *(trkdata[trk]+2); /* # clocks/met click */
ts32pq= *(trkdata[trk]+3); /* # 1/32 notes/MIDI clk*/
break;
case 0x59: /* Key Signature */
case 0x7f: /* Seq-specific event */
break;
} /* end switch */
trklen[trk] -= len2; /* Update rem len */
trkdata[trk]+=len2;
} else { /* not META event, try MIDI event */
/**************************************************************/
/* Process Status Byte (if any) */
/**************************************************************/
if (ch & 0x80) { /* Status Byte? (bit 7==1) */
/* Do we want to run status here? */
runstat[trk] = ch; /* save running status */
mrunstat = ch; /* and master */
chan = ch & 0x0f; /* Save channel # */
buff_data(ch); /* Write it */
ch = nextbyte(trk); /* Get next data byte */
} /* endif status byte */
/* We have to write status byte if we can't run */
if ( (runstat[trk] != mrunstat) /* Is status same? */
|| mrunstat==0) { /* or zero? */
mrunstat = runstat[trk]; /* if not, update it */
chan = mrunstat & 0x0f; /* Save channel # */
buff_data(mrunstat); /* Write it */
} /* endif status same */
/***********************************************************/
/* Process by status type */
/***********************************************************/
switch (runstat[trk] & 0xf0) { /* Handle by group */
case 0x80: /* Note Off */
buff_data(ch);
tptr = nextbyte(trk);
buff_data(tptr); /*Write 3rd byte */
/* Reduce count of total notes on */
if (--totnumnotes < 0) {
totnumnotes = 0;
} /* endif totnumnote < 0 */
/* Reduce count of # notes on */
if (--numnotes[chan] < 0) {
outmsg(WARNING,NOTES);
numnotes[chan] = 0;
} /* endif numnotes[chan] < 0 */
/* See of matching note-on */
for (x=0; x<16 && (keynums[chan][x]!=(char)ch); x++);
if (x<16) {
keynums[chan][x] = -1;
} /* endif x < 16 */
break;
case 0x90: /* Note On */
buff_data(ch);
b3 = nextbyte(trk); /* Get 3rd byte */
buff_data(b3); /* Write 3rd byte */
if (b3==0) { /* Note Off? */
/* Reduce count of total notes on */
if (--totnumnotes < 0) {
totnumnotes = 0;
} /* endif totnumnotes < 0 */
/* Reduce count of # notes on */
if (--numnotes[chan] < 0) {
outmsg(WARNING,NOTES);
numnotes[chan] = 0;
} /* endif numnotes[chan] < 0 */
/* See of matching note-on */
for (x=0; x<16 && (keynums[chan][x]!=(char)ch); x++);
if (x<16) {
keynums[chan][x] = -1;
} /* endif x < 16 */
} else { /* b <> 0 */
/* Increase count of total notes on */
if (++totnumnotes > totmaxnotes) {
/* Keep track of highest ever */
totmaxnotes = totnumnotes;
} /* endif totnumnotes ? totmaxnotes */
/* Increase count of # notes on */
if (++numnotes[chan] > maxnotes[chan]) {
/* Keep track of highest ever */
maxnotes[chan] = numnotes[chan];
} /* endif numnotes[chan] > maxnotes[chan] */
/* Assign a spot for it in keynums[] */
for (x=0; x<16 && keynums[chan][x] != -1; x++);
if (x<16) {
keynums[chan][x] = ch;
} /* endif x < 16 */
} /* endif b==0 */
break;
case 0xa0: /* Aftertouch */
buff_data(ch); /* Write it */
tptr = nextbyte(trk);
buff_data(tptr); /* Write 3rd byte */
break;
case 0xb0: /* Control Change */
buff_data(ch); /* Write it */
tptr = nextbyte(trk);
buff_data(tptr); /* Write 3rd byte */
break;
case 0xc0: /* Program Change */
buff_data(ch); /* Write it */
progchgs[chan]++; /* Keep count */
break;
case 0xd0: /* Channel pressure */
buff_data(ch); /* Write it */
break;
case 0xe0: /* Pitch bend */
buff_data(ch); /* Write it */
tptr = nextbyte(trk);
buff_data(tptr); /* Write 3rd byte */
break;
case 0xf0: /* System */
switch(runstat[trk]){
case 0xf0: /* System Exclusive */
break; /* (done above) */
case 0xf1: /* MTC Qtr Frame */
buff_data(ch); /* Write it */
break;
case 0xf2: /* SPP */
buff_data(ch); /* Write it */
tptr = nextbyte(trk);
buff_data(tptr); /* Write 3rd byte*/
break;
case 0xf3: /* Song Select */
case 0xf4: /* n/a */
case 0xf5: /* n/a */
case 0xf6: /* Tune Request*/
case 0xf7: /* EOX */
case 0xf8: /* Timing Clock*/
case 0xf9: /* n/a */
case 0xfa: /* Start */
case 0xfb: /* Continue */
case 0xfc: /* Stop */
case 0xfd: /* n/a */
case 0xfe: /* Active Sensing*/
case 0xff: /* System Reset*/
buff_data(ch); /* Write it */
break;
} /* end switch runstat[trk] */
default: /* None */
break;
} /* end switch runstat[trk] & 0xf0 */
} /* endif SYSEX event */
/* Reload delta time for this track */
if (trklen[trk] > 0) { /* Any more data ? */
delta[trk] = 0; /* Clear delta time */
do { /* get all delta bytes */
ch = nextbyte(trk); /* Read next byte */
delta[trk] = (delta[trk]<<7) /* Shift delta and */
+(ch & 0x7f); /* add next delta byte */
} while (ch & 0x80); /* Until bit 7 is clear */
} /* endif trklen[trk] > 0 */
} /* endif track still valid */
} /* end for track=0 to maxtrack */
} /* endif user_esc == FALSE */
} /* end while (remtracks & user_esc == FALSE) */
if (!user_esc) {
send_data(midi_buff,midi_buff_index,0);
if (audiowait) {
#if IS_DOS
if(rc = ioctl(0,AUDIO_WAIT,audhndl)){
#else
if(rc = DosDevIOCtl(0, NULL, 0x40+AUDIO_WAIT, 0x80, audhndl)) {
#endif
outmsg(ERROR,WAITIOCTL); /* Write failed return code */
_settextposition(11,30);
printf("%i",rc);
endemsg(ERROR);
close(audhndl);
close(inhndl);
freebuffs(xbuf->num_buffers,rbuf->num_buffers);
return(1);
}
update_count();
/* loop until get ESC character */
while(!user_esc) {
if (kbhit()) {
key_hit = getch();
if (key_hit == ESC) user_esc = TRUE;
}
}
} else {
while (!user_esc) {
key_hit=send_data(&ch,0,0); /* Waste time for music to finish*/
if ((xbuf->count <= 0) && (old_playtotal != playtotal)) {
old_playtotal = playtotal;
strcpy(status,"Finished");
_settextposition(12,((short)(strlen(help_msg[PLAYING1][3]))+5));
printf("%s",status);
if (batch) user_esc = TRUE;
if (!supress && (old_runtotal != runtotal)) {
old_runtotal = runtotal;
_settextposition(16,((short)(strlen(help_msg[PLAYING1][7]))+5));
printf("%6.6ld",runtotal);
if (pos_flag) {
_settextposition(11,((short)(strlen(extra_msg[POSITION]))+5));
printf("%6.6ld",xbuf->position);
} /* endif */
} /* endif */
if (!batch) {
while(!user_esc) {
if (kbhit()) {
key_hit = getch();
if (key_hit == ESC) user_esc = TRUE;
}
}
} /* endif */
} else if ((xbuf->count <= 0) && (batch)) user_esc = TRUE;
} /* end_while */
} /* endif audiowait */
} /* endif */
for (remtracks=0; remtracks<maxtrack; remtracks++) {
if(trkbuffer[remtracks]) free(trkbuffer[remtracks]);
} /* endfor */
return(0);
} /* end midi2seq */
/*****************************************************************************/
/* */
/* FUNCTION NAME = freebuffs */
/* */
/* FUNCTION = Free all allocated buffers. */
/* */
/* INPUT PARAMETERS = xnum - number of xbuf buffers to free */
/* rnum - number of rbuf buffers to free */
/* */
/* RETURN CODE = none */
/* */
/*****************************************************************************/
void freebuffs(unsigned int xnum, unsigned int rnum)
{
unsigned int num;
if (update_flag) {
if (function == PLAY_DEMO) {
num = xnum;
for (sy = 0; sy<rnum; sy++) {
if(rbuf->buf[sy].Virt) {
_ffree(rbuf->buf[sy].Virt);
rbuf->buf[sy].Virt = 0;
} /* endif */
} /* endfor */
} else {
num = rnum;
for (sy = 0; sy<xnum; sy++) {
if(xbuf->buf[sy].Virt) {
_ffree(xbuf->buf[sy].Virt);
xbuf->buf[sy].Virt = 0;
} /* endif */
} /* endfor */
} /* endif */
for (sy = 0; sy<num; sy++) {
if(update_array[sy].Virt) {
_ffree(update_array[sy].Virt);
update_array[sy].Virt = 0;
} /* endif */
} /* endfor */
} else {
for (sy = 0; sy<rnum; sy++) {
if(rbuf->buf[sy].Virt) {
_ffree(rbuf->buf[sy].Virt);
rbuf->buf[sy].Virt = 0;
} /* endif */
} /* endfor */
for (sy = 0; sy<xnum; sy++) {
if(xbuf->buf[sy].Virt) {
_ffree(xbuf->buf[sy].Virt);
xbuf->buf[sy].Virt = 0;
} /* endif */
} /* endfor */
} /* endif */
} /* end freebuffs */
/*****************************************************************************/
/* */
/* FUNCTION NAME = nextbyte */
/* */
/* FUNCTION = Retrieve next byte from track array accounting for end */
/* of data. */
/* */
/* INPUT PARAMETERS = track - array of MIDI track chunk data. */
/* */
/* RETURN CODE = ch - character read from array */
/* */
/*****************************************************************************/
unsigned char nextbyte(track)
int track;
{
unsigned char ch;
ch = *trkdata[track]++;
if (--trklen[track] == 0) { /* End of track */
delta[track] = 0xffffffff; /* Set max delta time */
remtracks--;
} /* endif trklen = 0 */
return(ch);
} /* end nextbyte */
/*****************************************************************************/
/* */
/* FUNCTION NAME = buff_data */
/* */
/* FUNCTION = Used to fill up intermediate buffer for midi2seq so */
/* send_data not called for every byte. */
/* Will only send data when >50 bytes in the buffer. */
/* */
/* */
/* INPUT PARAMETERS = character to be added */
/* */
/* RETURN CODE = none */
/* */
/*****************************************************************************/
void buff_data(unsigned char ch)
{
midi_buff[midi_buff_index++] = ch;
if (midi_buff_index >= MIDI_BUFF_LEN) {
send_data(midi_buff,midi_buff_index,0); /* Send data to the audio device */
midi_buff_index = 0;
} /* endif */
} /* end buff_data */
/*****************************************************************************/
/* */
/* FUNCTION NAME = seq2midi */
/* */
/* FUNCTION = Convert Audio DD output data to MIDI standard file. */
/* */
/* INPUT PARAMETERS = buffer - pointer to input data buffer to be xlated*/
/* count - length of data in buffer */
/* f8_count_ptr - ptr to variable with current # of */
/* F8 timing bytes from previous */
/* buffers to be added to sysex msg */
/* */
/* RETURN CODE = 0 Successful */
/* 1 Failure */
/* */
/*****************************************************************************/
int seq2midi(unsigned char *buffer, int count, unsigned long *f8_count_ptr)
{
unsigned char conv_buf[512];
unsigned char ch;
unsigned long temp_val, /* used in writing variable length data */
value; /* used in writing variable length data */
int j, /* index into conv_buff */
i,
ndata;
char flag; /* flag to break out of loop */
/*****************************************************************************/
/* LOCAL VARIABLE DEFINITIONS */
/*****************************************************************************/
i = 0; /* init index into buffer */
j = 0; /* init index into converted buffer */
do {
/***********************************************************************/
/* Check next byte - if new status then process it, else if same old */
/* status eat this byte. if not a status byte just put in buffer. */
/***********************************************************************/
if ((ch=buffer[i]) & 0x80) { /* check to see if status byte */
switch (ch & 0xF0) {
case NOTE_OFF:
case NOTE_ON:
case KEY_PRESSURE:
case CONTROL_CHANGE:
case PITCH_BEND:
data_bytes++; /* Need a total of 2 data bytes*/
/* get the other one below */
case PROGRAM_CHANGE:
case CHANNEL_PRESSURE:
data_bytes++; /* Need a total of 1 data byte */
last_data_bytes = data_bytes; /* remember total # of */
/* data bytes expected */
/* for this status */
if (*f8_count_ptr > 0) {
value = *f8_count_ptr; /* get any F8's from prev*/
/* buffer(s) */
*f8_count_ptr = 0; /* set back to zero now */
/* that these have been */
/* counted */
temp_val = value & 0x7F;
while (( value >>= 7) > 0) {
temp_val <<= 8;
temp_val |= 0x80;
temp_val += (value & 0x7F);
} /* end while */
/* put delay time into conv_buf */
flag = TRUE;
while (flag) {
conv_buf[j++] = (unsigned char)(temp_val & 0xFF);
if (temp_val & 0x80) {
temp_val >>= 8;
} else {
flag = FALSE;
} /* end if */
} /* end while */
} else { /* no previous F8's */
if (!delta_time) {
conv_buf[j++] = 0; /* Put in delta time of 0 */
} /* endif */
} /* endif */
delta_time = TRUE;
if (running_status != ch) {
conv_buf[j++] = ch; /* put status in output */
running_status = ch; /* update running status */
delta_time = FALSE;
} /* endif running status != ch */
i++; /* go to next character */
break;
/* No system exclusive messages (F0) should be seen coming */
/* from the device driver. The rest of the system messages */
/* F1-FF may be seen but should not be placed in the MIDI */
/* file and should be "eaten" with the exception of the */
/* TIMING_CLOCK which should be translated into a delta_time */
/* variable length value. */
default:
switch (ch) {
case TIMING_CLOCK:
/* determine how many ticks */
value = 1;
while ((++i < count) && (buffer[i] == TIMING_CLOCK))
value++;
if ((data_bytes <= 0) &&
(i < count)) { /* did F8's run off end of buf?*/
/* NO */
value += *f8_count_ptr;/* add any F8's from prev*/
/* buffer(s) */
*f8_count_ptr = 0; /* set back to zero now */
/* that these have been */
/* counted */
temp_val = value & 0x7F;
while (( value >>= 7) > 0) {
temp_val <<= 8;
temp_val |= 0x80;
temp_val += (value & 0x7F);
} /* end while */
/* put delay time into conv_buf */
flag = TRUE;
while (flag) {
conv_buf[j++] = (unsigned char)(temp_val & 0xFF);
if (temp_val & 0x80) {
temp_val >>= 8;
} else {
flag = FALSE;
} /* end if */
} /* end while */
delta_time = TRUE;
} else { /* whole message not here */
*f8_count_ptr += value;
} /* endif */
break;
case MTC_QUARTER_FRAME:
case SELECT_SONG:
eat = 1; /* be sure and eat the next data */
i++; /* byte that comes through */
break;
case SONG_POSITION:
eat = 2; /* be sure and eat the next 2 data*/
i++; /* bytes that come through */
break;
case 0xF0:
while (buffer[i++] != 0xF7); /* eat all bytes until EOX*/
break;
case TUNE_REQUEST:
case EOX:
case START:
case CONT:
case STOP:
case ACTIVE_SENSING:
case SYSTEM_RESET:
default:
i++; /* eat this byte and continue */
break;
} /* end switch (ch) */
break;
} /* end switch (ch & 0xF0) */
} else { /* not a status byte - must be data byte */
if (data_bytes == 0) {
/* this byte was not expected which means*/
/* that no status was given (running */
/* status to be used and F8's should be */
/* handled now */
if (*f8_count_ptr > 0) {
value = *f8_count_ptr; /* get any F8's from prev*/
/* buffer(s) */
*f8_count_ptr = 0; /* set back to zero now */
/* that these have been */
/* counted */
temp_val = value & 0x7F;
while (( value >>= 7) > 0) {
temp_val <<= 8;
temp_val |= 0x80;
temp_val += (value & 0x7F);
} /* end while */
/* put delay time into conv_buf */
flag = TRUE;
while (flag) {
conv_buf[j++] = (unsigned char)(temp_val & 0xFF);
if (temp_val & 0x80) {
temp_val >>= 8;
} else {
flag = FALSE;
} /* end if */
} /* end while */
} else { /* no F8's - means a delta time of 0 or F8's just */
/* written out */
if (!delta_time) {
conv_buf[j++] = 0; /* put in 0 delta time */
} /* endif */
} /* endif */
delta_time = TRUE;
data_bytes = last_data_bytes; /* init # of bytes for this */
/* running status */
} /* endif data_bytes = 0 */
data_bytes--; /* subtract this data byte */
if (eat) {
eat--;
} else { /* don't eat it */
conv_buf[j++] = ch; /* put in convert buffer */
delta_time = FALSE; /* just wrote in data - so */
/* delta_time no longer last */
/* thing written */
} /* end if (eat */
i++;
} /* endif */
} while ( (i < count) && (!kbhit()) ); /* enddo */
if (j > 0) {
/* Write out the buffer */
ndata = (unsigned)write(inhndl,(char *)conv_buf,j);
if(ndata==65535){
outmsg(HELP,CLEARSCRN);
outmsg(ERROR,DISKFULL);
_settextposition(10,30);
printf("%s", iname);
endemsg(ERROR);
return (1);
} /* endif fwrite */
} /* endif */
return((int)i);
} /* end seq2midi */
/*****************************************************************************/
/* */
/* FUNCTION NAME = dcwrite */
/* */
/* FUNCTION = Direct buffer write. */
/* */
/* INPUT PARAMETERS = data - data to be written to buffer */
/* len - amount of data to be written */
/* */
/* RETURN CODE = none */
/* */
/*****************************************************************************/
void dcwrite(data,len,num_buffers)
char *data;
int len;
unsigned int num_buffers;
{
while(len--){
while(xbuf->count == xbuf->size); /* Wait until there's room */
*xbuf->head = *data++; /* Copy a byte */
xbuf->runflags |= IOBUF_LOCK;
++xbuf->count;
xbuf->runflags &= ~IOBUF_LOCK;
/* Time to wrap ptr? */
if(++xbuf->head >= xbuf->buf[xbuf->head_segnum].Virt+xbuf->buf[xbuf->head_segnum].length){
if (++xbuf->head_segnum >= num_buffers) {
xbuf->head_segnum = 0;
} /* endif */
xbuf->head = xbuf->buf[xbuf->head_segnum].Virt;
} /* end if */
} /* end while */
}
#if IS_DOS
/*****************************************************************************/
/* */
/* FUNCTION NAME = ioctl */
/* */
/* FUNCTION = Issue DOS IOCTL. */
/* */
/* INPUT PARAMETERS = Data - pointer to data structure for IOCTL */
/* Function - IOCTL funtion */
/* DevHandle - Audio device handle */
/* */
/* RETURN CODE = none */
/* */
/*****************************************************************************/
int ioctl(Data,Function,DevHandle)
void far *Data;
unsigned char Function;
int DevHandle;
{
int rc;
#if 0
_asm{
push ds
mov ax,440ch
mov bx,DevHandle
mov cl,Function
add cl,40h
mov ch,0x80 ; Category
lds dx,Data
int 21h
pop ds
jc error
mov ax,0
error:
mov rc,ax
}
#else
union REGS dosregs;
struct SREGS segregs;
dosregs.x.ax=0x440c;
dosregs.x.bx=DevHandle;
dosregs.h.cl=(char)(Function+0x40);
dosregs.h.ch=0x80;
dosregs.x.dx=FP_OFF(Data);
segregs.ds=FP_SEG(Data);
intdosx(&dosregs,&dosregs,&segregs);
if(dosregs.x.cflag==0) rc=0;
else rc=dosregs.x.ax;
#endif
return(rc);
}
/*****************************************************************************/
/* */
/* FUNCTION NAME = dspload */
/* */
/* FUNCTION = Load module onto DSP (DOS version) */
/* */
/* INPUT PARAMETERS = name - DSP module name to be loaded */
/* audstr - name of audio device */
/* */
/* RETURN CODE = 0 - successful */
/* -1 - failed */
/* */
/*****************************************************************************/
int dspload(name,audstr)
char *name;
int audstr;
{
FILE *str;
struct audio_load load;
unsigned long sz;
char *buf;
audstr = audstr; /* For compiler warning - also to make call*/
/* compatible with OS/2 call */
if(!(str=fopen(name,"rb"))){
outmsg(ERROR,DSPOPEN);
_settextposition(11,30);
printf("%s",name);
endemsg(ERROR);
return(-1);
}
fseek(str,-1,SEEK_END); /* Determine size */
sz = ftell(str)+1;
if(!(buf = malloc((size_t)sz))){
outemsg(ERROR,NOMEMDSP);
if(buf) free(buf);
fclose(str);
return(-1);
}
fseek(str,0,SEEK_SET); /* Seek to beginning */
fread(buf,1,(int)sz,str);
fclose(str);
load.buffer = buf; /* Issue load IOCTL */
load.size = sz;
load.flags = LOAD_START | LOAD_END;
if(direct_call == NULL){
ioctl(&load,AUDIO_LOAD,audhndl);
}else{
(*direct_call)(EP_LOAD,(char far *)&load,23);
}
if(buf) free(buf);
return(0);
} /* end dspload for DOS */
#else /* OS/2 mode DSPLOAD module */
/*****************************************************************************/
/* */
/* FUNCTION NAME = dspload */
/* */
/* FUNCTION = Load module onto DSP (OS/2 version) */
/* */
/* INPUT PARAMETERS = name - DSP module name to be loaded */
/* audstr - name of audio device */
/* */
/* RETURN CODE = 0 - successful */
/* -1 - failed */
/* */
/*****************************************************************************/
int dspload(name,audstr)
char *name;
HFILE audstr;
{
FILE *str;
struct audio_load load;
char buf[256];
if(!(str=fopen(name,"rb"))){
outmsg(ERROR,DSPOPEN);
_settextposition(11,30);
printf("%s",name);
endemsg(ERROR);
return(-1);
}
load.buffer = buf; /* Issue load IOCTL */
load.flags = LOAD_START;
do{
load.size = fread(buf,1,256,str);
if(load.size != 256) load.flags |= LOAD_END; /* Last block */
if(DosDevIOCtl(&load, NULL, 0x40+AUDIO_LOAD, 0x80, audstr) != 0) { /* load it */
outemsg(ERROR,EAUDIOLOAD);
fclose(str);
return(-1);
}
load.flags = 0;
}while(load.size == 256);
fclose(str);
return(0);
} /* end DSPLOAD for OS/2 mode */
#endif
/*****************************************************************************/
/* */
/* FUNCTION NAME = change_settings */
/* */
/* FUNCTION = Change the Volume/Balance setting */
/* */
/* INPUT PARAMETERS = none */
/* */
/* RETURN CODE = none */
/* */
/*****************************************************************************/
void change_settings()
{
#if IS_OS2
int rc;
#endif
struct audio_control control;
struct audio_change change;
_settextposition(13,((short)(strlen(help_msg[PLAYING1][4]))+5));
printf("%s",cur_volume_s);
_settextposition(14,((short)(strlen(help_msg[PLAYING1][5]))+5));
printf("%s",cur_balance_s);
/* Issue CHANGE IOCtl */
control.position = 0; /* Do it now */
control.ioctl_request = AUDIO_CHANGE; /* Change configuration */
control.return_code = 0; /* zero out return code field */
control.request_info = &change; /* Request data = change struct*/
change.input_list[0].devtype = cur_input;
change.input_list[0].devnum = DEVICE_1;
change.output_list[0].devtype = source_output;
change.output_list[0].devnum = DEVICE_1;
change.input_list[1].devtype = NULL_INPUT;
change.input_list[1].devnum = DEVICE_1;
change.output_list[1].devtype = NULL_OUTPUT;
change.output_list[1].devnum = DEVICE_1;
change.input = INPUTS_LISTED;
change.output = OUTPUTS_LISTED; /* Output select */
change.monitor = monitor; /* Monitor not applicable */
change.volume = cur_volume; /* Volume set to maximum */
change.volume_delay = delay; /* Set volume across 5 seconds*/
change.balance = cur_balance; /* Balance set to mid-point */
change.balance_delay = delay; /* Set balance in 5 seconds */
change.treble = 0x3fffffff; /* Mid point */
change.bass = 0x3fffffff; /* Mid point */
change.pitch = 0; /* */
if (mastervol) {
change.dev_info = &devinfo; /* Device dependent data */
} else {
change.dev_info = NULL; /* No device dependent data */
}
change.input_gain = 0; /* No input gain */
change.mode_info = NULL; /* No mode dependent data */
#if IS_OS2
if((rc = DosDevIOCtl(&control, NULL, 0x40+AUDIO_CONTROL, 0x80, audhndl)) ||
(control.return_code == 12)) {
outmsg(ERROR,ECHNGIOCTL);
_settextposition(11,30);
printf("%i %i",rc,control.return_code);
endemsg(ERROR);
close(audhndl);
close(inhndl);
} /* endif rc = audio_ioctl */
#else
if(direct_call == NULL){
ioctl(&control,AUDIO_CONTROL,audhndl);
}else{
(*direct_call)(EP_CONTROL,(char far *)&control,23);
}
#endif
} /* end change_settings */
/*****************************************************************************/
/* */
/* FUNCTION NAME = outemsg */
/* */
/* FUNCTION = Output error message to display and call endemsg. */
/* */
/* INPUT PARAMETERS = type - type of message to be output */
/* msg_num - message number */
/* */
/* RETURN CODE = none */
/* */
/*****************************************************************************/
void outemsg(type,msg_num)
int type;
int msg_num;
{
outmsg(type,msg_num);
endemsg(type);
} /* end outemsg */
/*****************************************************************************/
/* */
/* FUNCTION NAME = endemsg */
/* */
/* FUNCTION = Output status message to the display */
/* and then wait for key to be hit and then clear */
/* the screen. */
/* */
/* INPUT PARAMETERS = type - type of message to be output */
/* */
/* RETURN CODE = none */
/* */
/*****************************************************************************/
void endemsg(type)
int type;
{
outmsg(STATUS,CONTINUE);
getch();
outmsg(type,CLEARSCRN);
outmsg(STATUS,CLEARSCRN);
} /* endemsg */
/*****************************************************************************/
/* */
/* FUNCTION NAME = outmsg */
/* */
/* FUNCTION = Output a message to the display. */
/* */
/* INPUT PARAMETERS = type - type of message to be output */
/* msg_num - message number */
/* */
/* RETURN CODE = none */
/* */
/*****************************************************************************/
void outmsg(type, msg_num)
int type;
int msg_num;
{
switch(type) {
case STATUS:
_settextposition(21,5);
if (msg_num == CLEARSCRN) {
_setbkcolor(BLUE); /* Set background color */
_settextcolor(BLUE); /* Set foreground/text color */
_outtext(BLANK_70); /* Display the status message */
} else { /* a real message to put out */
_setbkcolor(GREEN); /* Set background color */
_settextcolor(BLACK); /* Set foreground/text color */
_outtext(status_msg[msg_num][0]); /* Disp the status message */
} /* endif msg_num = CLRSCRN */
break;
case VBHELP:
_settextposition(22,5);
if (msg_num == CLEARSCRN) {
_setbkcolor(BLUE); /* Set background color */
_settextcolor(BLUE); /* Set foreground/text color */
_outtext(BLANK_70); /* Clear the status message */
} else { /* a real message to put out */
_setbkcolor(GREEN); /* Set background color */
_settextcolor(BLACK); /* Set foreground/text color */
_outtext(vbhelp_msg[msg_num][0]); /* Disp the vol/bal message */
} /* endif msg_num = CLRSCRN */
break;
case USERINPUT:
if (msg_num == CLEARSCRN) {
_setbkcolor(BLUE); /* Set background color */
_settextcolor(BLUE); /* Set foreground/text color */
_settextposition(5,5);
_outtext(BLANK_70);
_settextposition(6,5);
_outtext(BLANK_70);
_settextposition(7,5);
_outtext(BLANK_70);
} else { /* a real message to put out */
_setbkcolor(BLUE); /* Set background color */
_settextcolor(WHITE); /* Set foreground/text color */
/* Display the user input message */
_settextposition(5,5);
_outtext(user_msg[msg_num][0]);
_settextposition(6,5);
_outtext(user_msg[msg_num][1]);
_settextposition(7,5);
_outtext(BLANK_70);
} /* endif msg_num = CLRSCRN */
break;
case ERROR:
if (msg_num == CLEARSCRN) {
_setbkcolor(BLUE); /* Set background color */
_settextcolor(BLUE); /* Set foreground/text color */
_settextposition(9,5);
_outtext(BLANK_70);
_settextposition(10,5);
_outtext(BLANK_70);
_settextposition(11,5);
_outtext(BLANK_70);
_settextposition(12,5);
_outtext(BLANK_70);
} else { /* a real message to put out */
_setbkcolor(RED); /* Set background color */
_settextcolor(BLACK); /* Set foreground/text color */
/* Display the error message */
_settextposition(9,5);
_outtext(error_msg[msg_num][0]);
_settextposition(10,5);
_outtext(error_msg[msg_num][1]);
_settextposition(11,5);
_outtext(error_msg[msg_num][2]);
_settextposition(12,5);
_outtext(error_msg[msg_num][3]);
} /* endif msg_num = CLRSCRN */
break;
case WARNING:
if ((msg_num == CLEARSCRN) || (msg_num == BLANK)) {
if (msg_num == CLEARSCRN) {
_setbkcolor(BLUE); /* Set background color */
_settextcolor(BLUE); /* Set foreground/text color */
} else { /* BLANK */
_setbkcolor(GRAY); /* Set background color */
_settextcolor(RED); /* Set foreground/text color */
} /* endif */
_settextposition(18,5);
_outtext(BLANK_70);
_settextposition(19,5);
_outtext(BLANK_70);
_settextposition(20,5);
_outtext(BLANK_70);
} else { /* a real message to put out */
_setbkcolor(GRAY); /* Set background color */
_settextcolor(RED); /* Set foreground/text color */
/* Display the warning message */
_settextposition(18,5);
_outtext(warning_msg[msg_num][0]);
_settextposition(19,5);
_outtext(warning_msg[msg_num][1]);
_settextposition(20,5);
_outtext(warning_msg[msg_num][2]);
} /* endif msg_num = CLRSCRN */
break;
case HELP:
if ((msg_num == CLEARSCRN) || (msg_num == BLANK)) {
if (msg_num == CLEARSCRN) {
_setbkcolor(BLUE); /* Set background color */
_settextcolor(BLUE); /* Set foreground/text color */
} else { /* BLANK */
_setbkcolor(AQUA); /* Set background color */
_settextcolor(BLACK); /* Set foreground/text color */
} /* endif */
_settextposition(9,5);
_outtext(BLANK_70);
_settextposition(10,5);
_outtext(BLANK_70);
_settextposition(11,5);
_outtext(BLANK_70);
_settextposition(12,5);
_outtext(BLANK_70);
_settextposition(13,5);
_outtext(BLANK_70);
_settextposition(14,5);
_outtext(BLANK_70);
_settextposition(15,5);
_outtext(BLANK_70);
_settextposition(16,5);
_outtext(BLANK_70);
_settextposition(17,5);
_outtext(BLANK_70);
} else { /* a real message to put out */
_setbkcolor(AQUA); /* Set background color */
_settextcolor(BLACK); /* Set foreground/text color */
/* Display the help message */
_settextposition(9,5);
_outtext(help_msg[msg_num][0]);
_settextposition(10,5);
_outtext(help_msg[msg_num][1]);
_settextposition(11,5);
_outtext(help_msg[msg_num][2]);
_settextposition(12,5);
_outtext(help_msg[msg_num][3]);
_settextposition(13,5);
_outtext(help_msg[msg_num][4]);
_settextposition(14,5);
_outtext(help_msg[msg_num][5]);
_settextposition(15,5);
_outtext(help_msg[msg_num][6]);
_settextposition(16,5);
_outtext(help_msg[msg_num][7]);
_settextposition(17,5);
_outtext(help_msg[msg_num][8]);
} /* endif msg_num = CLRSCRN */
break;
case YNQUEST:
_settextposition(8,5);
if (msg_num == CLEARSCRN) {
_setbkcolor(BLUE); /* Set background color */
_settextcolor(BLUE); /* Set foreground/text color */
_outtext(BLANK_70); /* Display the Y/N question */
} else { /* a real message to put out */
_setbkcolor(BLUE); /* Set background color */
_settextcolor(WHITE); /* Set foreground/text color */
_outtext(ynquest_msg[msg_num][0]); /* Disp the Y/N question */
} /* endif msg_num = CLRSCRN */
break;
case TITLE:
if (msg_num == CLEARSCRN) {
_setbkcolor(BLUE); /* Set background color */
_settextcolor(BLUE); /* Set foreground/text color */
_settextposition(2,1);
_outtext(BLANK_70);
_settextposition(3,1);
_outtext(BLANK_70);
} else { /* a real message to put out */
_setbkcolor(BLUE); /* Set background color */
_settextcolor(WHITE); /* Set foreground/text color */
/* Display the title message */
_settextposition(2,1);
_outtext(title_msg[msg_num][0]);
_settextposition(3,1);
_outtext(title_msg[msg_num][1]);
} /* endif msg_num = CLRSCRN */
break;
case COPYRIGHT:
_setbkcolor(BLUE); /* Set background color */
_settextcolor(WHITE); /* Set foreground/text color */
_settextposition(24,1); /* Write out copyright msg to display */
_outtext(copyright_msg[msg_num][0]);
break;
case CLHELP:
_setbkcolor(BLUE); /* Set background color */
_settextcolor(WHITE); /* Set foreground/text color */
/* Display the title message */
_settextposition(3,1);
_outtext(clhelp_msg[msg_num][0]);
_settextposition(4,1);
_outtext(clhelp_msg[msg_num][1]);
_settextposition(5,1);
_outtext(clhelp_msg[msg_num][2]);
_settextposition(6,1);
_outtext(clhelp_msg[msg_num][3]);
_settextposition(7,1);
_outtext(clhelp_msg[msg_num][4]);
_settextposition(8,1);
_outtext(clhelp_msg[msg_num][5]);
_settextposition(9,1);
_outtext(clhelp_msg[msg_num][6]);
_settextposition(10,1);
_outtext(clhelp_msg[msg_num][7]);
_settextposition(11,1);
_outtext(clhelp_msg[msg_num][8]);
_settextposition(12,1);
_outtext(clhelp_msg[msg_num][9]);
_settextposition(13,1);
_outtext(clhelp_msg[msg_num][10]);
_settextposition(14,1);
_outtext(clhelp_msg[msg_num][11]);
_settextposition(15,1);
_outtext(clhelp_msg[msg_num][12]);
_settextposition(16,1);
_outtext(clhelp_msg[msg_num][13]);
_settextposition(17,1);
_outtext(clhelp_msg[msg_num][14]);
_settextposition(18,1);
_outtext(clhelp_msg[msg_num][15]);
_settextposition(19,1);
_outtext(clhelp_msg[msg_num][16]);
_settextposition(20,1);
_outtext(clhelp_msg[msg_num][17]);
_settextposition(21,1);
_outtext(clhelp_msg[msg_num][18]);
_settextposition(22,1);
break;
} /* end switch (type) */
} /* end outmsg */
/*****************************************************************************/
/* */
/* FUNCTION NAME = read_kb */
/* */
/* FUNCTION = Read a character from stream input */
/* */
/* INPUT PARAMETERS = string_read - ptr to string to be read */
/* length - max length of string */
/* */
/* RETURN CODE = character read */
/* */
/*****************************************************************************/
int read_kb(char *string_read,unsigned int length)
{
unsigned int x;
int ch;
unsigned int string_len;
int finished;
for (x=0; x<length; x++) {
string_read[x] = '\0';
} /* end for */
finished = FALSE;
while (!(finished)) {
ch = getch();
switch(ch) {
case ENTER10:
case ENTER13:
finished = TRUE;
break;
case ESC:
return(1);
break;
case SPACE:
break;
case BACKSPACE:
if (string_len = strlen(string_read)) {
putch(BACKSPACE);
putch(SPACE);
putch(BACKSPACE);
string_read[string_len-1] = '\0';
} /* endif */
break;
case UP_ARROW:
string_len = strlen(old_string_read);
for (x=0; x<string_len; x++) {
putch(old_string_read[x]);
strcat(string_read,(char *)&old_string_read[x]);
} /* endfor */
break;
default:
if (strlen(string_read) <= (length-1)) {
putch(ch);
strcat(string_read,(char *)&ch);
} /* endif */
} /* switch */
} /* endwhile */
for (x=0; x<length; x++) {
old_string_read[x] = '\0';
} /* end for */
string_len = strlen(string_read);
for (x=0; x<string_len; x++) {
strcat(old_string_read,(char *)&string_read[x]);
} /* endfor */
return(0);
} /* end read_kb */